diff --git a/Functors-Applicatives-Monads-In-Pictures.playground/Contents.swift b/Functors-Applicatives-Monads-In-Pictures.playground/Contents.swift index bc61c9b..4519491 100644 --- a/Functors-Applicatives-Monads-In-Pictures.playground/Contents.swift +++ b/Functors-Applicatives-Monads-In-Pictures.playground/Contents.swift @@ -1,3 +1,6 @@ + + + //: This is a companion Playground for the article "Swift Functors, Applicatives, and Monads in Pictures", available at http://www.mokacoding.com/blog/functor-applicative-monads-in-pictures/ //: The article itself is a translation of the original "Functors, Applicatives, and Monads in Pictures" written for Haskell by Aditya Bhargava, available at http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html //: @@ -18,42 +21,43 @@ func plusThree(addend: Int) -> Int { return addend + 3 } -Optional.Some(2).map(plusThree) +Optional.some(2).map(plusThree) //: We can use autoclosures and be more succint -Optional.Some(2).map { $0 + 3 } +Optional.some(2).map { $0 + 3 } //: If the optional value is .None, map will return .None (nil) -Optional.None.map { $0 + 3 } +Optional.none.map { $0 + 3 } //: Map implementation might look like this -func myMap(a: T?, f: T -> U) -> U? { +func myMap(a: T?, f: (T) -> U) -> U? { switch a { - case .Some(let x): return f(x) - case .None: return .None + case .some(let x): return f(x) + case .none: return .none } } -myMap(Optional.Some(2), f: { $0 + 3 }) +myMap(a: Optional.some(2), f: { $0 + 3 }) //: We can define an infix operator -infix operator <^> { associativity left } +infix operator <^>: MultiplicationPrecedence -func <^>(f: T -> U, a: T?) -> U? { +func <^>(f: (T) -> U, a: T?) -> U? { return a.map(f) } -plusThree <^> Optional.Some(2) +plusThree <^> Optional.some(2) //: Turns out functions can be mapped as well. Functions are functors too! -typealias IntFunction = Int -> Int +typealias IntFunction = (Int) -> Int -func map(f: IntFunction, _ g: IntFunction) -> IntFunction { +func map(_ + f: @escaping IntFunction, _ g: @escaping IntFunction) -> IntFunction { return { x in f(g(x)) } } @@ -62,16 +66,17 @@ foo(10) //: ## Applicative extension Optional { - func apply(f: (Wrapped -> U)?) -> U? { + func apply(_ f: ((Wrapped) -> U)?) -> U? { switch f { - case .Some(let someF): return self.map(someF) - case .None: return .None + case .some(let someF): return self.map(someF) + case .none: return .none } } } extension Array { - func apply(fs: [Element -> U]) -> [U] { + func apply(_ + fs: [(Element) -> U]) -> [U] { var result = [U]() for f in fs { for element in self.map(f) { @@ -82,50 +87,60 @@ extension Array { } } -infix operator <*> { associativity left } +infix operator <*>: MultiplicationPrecedence -func <*>(f: (T -> U)?, a: T?) -> U? { +func <*>(f: ((T) -> U)?, a: T?) -> U? { return a.apply(f) } -func <*>(f: [T -> U], a: [T]) -> [U] { +func <*>(f: [(T) -> U], a: [T]) -> [U] { return a.apply(f) } -Optional.Some({ $0 + 3 }) <*> Optional.Some(2) +Optional.some({ $0 + 3 }) <*> Optional.some(2) let arrayApplicative = [ { $0 + 3 }, { $0 * 2 } ] <*> [1, 2, 3] //: _Playground (as of Xcode 7 Beta 3) doesn't seem to be happy show the result of array applications , so we'll print open the console with Cmd + Y to see it_ print(arrayApplicative) -func curriedAddition(a: Int)(b: Int) -> Int { +public func curry(_ function: @escaping (A, B) -> C) -> (A) -> (B) -> C { + return { (a: A) -> (B) -> C in { (b: B) -> C in function(a, b) } } +} + +func addition(a: Int, b: Int) -> Int { return a + b } +let curriedAddition = curry(addition) + +curriedAddition(2)(3) + curriedAddition <^> Optional(2) <*> Optional(3) -func curriedTimes(a: Int)(b: Int) -> Int { - return a * b +func multiplication(a: Int, b: Int) -> Int { + return a * b } +let curriedTimes = curry(multiplication) + curriedTimes <^> Optional(5) <*> Optional(3) //: ## Monads -infix operator >>- { associativity left } +infix operator >>- : MultiplicationPrecedence -func >>-(a: T?, f: T -> U?) -> U? { +func >>-(a: T?, f: (T) -> U?) -> U? { return a.flatMap(f) } func half(a: Int) -> Int? { - return a % 2 == 0 ? a / 2 : .None + return a % 2 == 0 ? a / 2 : .none } Optional(3) >>- half Optional(4) >>- half -Optional.None >>- half +Optional.none >>- half //: We can even chain >>- diff --git a/Functors-Applicatives-Monads-In-Pictures.playground/contents.xcplayground b/Functors-Applicatives-Monads-In-Pictures.playground/contents.xcplayground index ee7c14f..89da2d4 100644 --- a/Functors-Applicatives-Monads-In-Pictures.playground/contents.xcplayground +++ b/Functors-Applicatives-Monads-In-Pictures.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/Functors-Applicatives-Monads-In-Pictures.playground/playground.xcworkspace/contents.xcworkspacedata b/Functors-Applicatives-Monads-In-Pictures.playground/playground.xcworkspace/contents.xcworkspacedata old mode 100644 new mode 100755 diff --git a/Functors-Applicatives-Monads-In-Pictures.playground/timeline.xctimeline b/Functors-Applicatives-Monads-In-Pictures.playground/timeline.xctimeline index 9064524..5e75c23 100644 --- a/Functors-Applicatives-Monads-In-Pictures.playground/timeline.xctimeline +++ b/Functors-Applicatives-Monads-In-Pictures.playground/timeline.xctimeline @@ -3,72 +3,72 @@ version = "3.0"> diff --git a/README.md b/README.md old mode 100644 new mode 100755