Last active
June 5, 2016 23:21
-
-
Save brianpartridge/34082d37f26ec549f6e7d496b6148e79 to your computer and use it in GitHub Desktop.
Swift implementation of http://adit.io/posts/2013-06-10-three-useful-monads.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* I'm still trying to wrap my head around this monad. | |
* Examples either seem contrived or do not use multiple | |
* types; it's not very useful for understanding when | |
* every input and output is a string. | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* On hold until I fully grasp Reader. */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol Concatable { | |
func byConcatenating(content: Self) -> Self | |
} | |
extension Array: Concatable { | |
func byConcatenating(content: Array) -> Array { | |
var mutableArray = self | |
mutableArray.appendContentsOf(content) | |
return mutableArray | |
} | |
} | |
protocol WriterType { | |
associatedtype Value | |
associatedtype Log | |
init(value: Value, log: Log) | |
var value: Value { get } | |
var log: Log { get } | |
} | |
class Writer<Value, Log: Concatable>: WriterType { | |
required init(value: Value, log: Log) { | |
self.value = value | |
self.log = log | |
} | |
let value: Value | |
let log: Log | |
func flatMap<U>(@noescape f:(Value) -> Writer<U, Log>) -> Writer<U, Log> { | |
let newWriter = f(value) | |
return Writer<U, Log>(value: newWriter.value, log: log.byConcatenating(newWriter.log)) | |
} | |
} | |
extension Writer: CustomStringConvertible { | |
var description: String { | |
return "Value: \(value), Log: \(log)" | |
} | |
} | |
func half(input: Int) -> Int { | |
return input / 2 | |
} | |
func triple(input: Int) -> Int { | |
return input * 3 | |
} | |
func stringify(input: Int) -> String { | |
return "\(input)" | |
} | |
half(8) | |
half(half(8)) | |
stringify(half(triple(half(8)))) | |
typealias StringArray = [String] | |
func half2(input:Int) -> Writer<Int, StringArray> { | |
return Writer(value: half(input), log: ["I just halved \(input)!"]) | |
} | |
func triple2(input: Int) -> Writer<Int, StringArray> { | |
return Writer(value: triple(input), log: ["I just tripled \(input)!"]) | |
} | |
func stringify2(input: Int) -> Writer<String, StringArray> { | |
return Writer(value: stringify(input), log: ["I just stringified \(input)"]) | |
} | |
half2(8) | |
half2(8).flatMap(triple2).flatMap(half2).flatMap(stringify2) | |
func makeWritable<T, U>(name: String, _ f: T -> U) -> (T -> Writer<U, StringArray>) { | |
return { input in Writer(value: f(input), log: ["\(name) \(input)"]) } | |
} | |
let half3 = makeWritable("halved", half) | |
let triple3 = makeWritable("tripled", triple) | |
let stringify3 = makeWritable("stringified", stringify) | |
half3(8) | |
half3(8).flatMap(triple3).flatMap(half3).flatMap(stringify3) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment