swift 1-Functor-and-Monad.md
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swift 1-Functor-and-Monad.md相关的知识,希望对你有一定的参考价值。
Copy and paste the swift code below into a playground to experiment.
This is a very close emulation of Functor and Monad typeclasses in swift. As of Swift 1.2 and Xcode 6.3, this is no longer very fragile.
Unfortunately, the compiler cannot verify the types when passing a function to `(>>=)`. We have to wrap the function in a closure and call it with an explicit argument to compile.
```swift
optionalDoubles >>= squareRoot // doesn't compile
optionalDoubles >>= { squareRoot($0) } // compiles
```
import Foundation
protocol Functor {
typealias A
typealias B
typealias FB
func fmap(A -> B) -> FB
}
protocol Monad: Functor {
static func unit(f: A) -> Self
func bind(f : A -> FB) -> FB
func >>=(x: Self, f : A -> FB) -> FB
}
infix operator >>= { associativity left }
func >>=<M: Monad>(x: M, f: M.A -> M.FB) -> M.FB {
return x.bind(f)
}
func bind<M: Monad>(x: M, f: M.A -> M.FB) -> M.FB {
return x.bind(f)
}
func unit<M: Monad>(a: M.A) -> M {
return M.unit(a)
}
/**
Make Array a functor
*/
extension Array: Functor {
typealias A = T
typealias B = Any
typealias FB = [B]
func fmap<B>(f: A -> B) -> [B] {
return self.map(f)
}
}
/**
Make Array a monad
*/
extension Array: Monad {
static func unit(x: A) -> [A] {
return [x]
}
func bind<B>(f: A -> [B]) -> [B] {
return self.map(f).reduce([], combine: +)
}
}
/**
Make optional a functor
*/
extension Optional: Functor {
typealias A = T
typealias B = Any
typealias FB = B?
func fmap<B>(f: A -> B) -> B? {
return self.map(f)
}
}
/**
Make optional a monad
*/
extension Optional: Monad {
static func unit(x: A) -> A? {
return Optional<A>.Some(x)
}
func bind<B>(f: A -> B?) -> B? {
return self.flatMap(f)
}
}
extension String: Functor {
typealias A = Character
typealias B = Character
typealias FB = String
func fmap<B>(f: A -> B) -> String {
return "".join(self.characters.map { String(f($0) as! Character) })
}
}
extension String: Monad {
static func unit(c: A) -> String {
return String(c)
}
func bind(f: A -> FB) -> String {
return "".join(self.characters.map(f))
}
}
func square(x: Double) -> Double {
return x * x
}
func invert(x: Double) -> Double? {
return fabs(x) > 0.0 ? 1.0 / x : nil
}
func squareRoot(x: Double) -> Double? {
return x > 0.0 ? sqrt(x) : nil
}
func test(x: Double) -> String {
return "test: \(x)"
}
let lettersArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz".characters.map { $0 }
func rot13(input: Character) -> Character {
if let i = lettersArray.indexOf(input) {
return lettersArray[i + 13 % Int(lettersArray.count)]
} else {
return input
}
}
/**
Let's take Functor and Monad out for a spin...
*/
let xs = [2.0, 3.0, 5.0, 7.0, 11.0, 13.0, 17.0]
xs.fmap(square)
let optionalXs: [Double?] = [2.0, nil, 5.0, 7.0, 11.0, 13.0, 17.0]
optionalXs.fmap { $0.fmap(square) }
let optional2: Double? = 2
optional2.fmap(test)
optional2.bind(squareRoot)
optional2 >>= { squareRoot($0) }
"hello world".fmap(rot13)
"hello world" >>= { unit(rot13($0)) }
以上是关于swift 1-Functor-and-Monad.md的主要内容,如果未能解决你的问题,请参考以下文章