Skip to content

Instantly share code, notes, and snippets.

@brianpartridge
Last active June 5, 2016 23:21
Show Gist options
  • Save brianpartridge/34082d37f26ec549f6e7d496b6148e79 to your computer and use it in GitHub Desktop.
Save brianpartridge/34082d37f26ec549f6e7d496b6148e79 to your computer and use it in GitHub Desktop.
/* 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.
*/
/* On hold until I fully grasp Reader. */
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