|
import Foundation |
|
|
|
public struct K<A> {} |
|
|
|
public protocol Functor { |
|
typealias _A |
|
typealias _B |
|
typealias _FB = K<_B> |
|
|
|
func fmap (_A -> _B) -> _FB |
|
} |
|
|
|
/** |
|
Using this global fmap usually crashes :( |
|
*/ |
|
public func fmap <F: Functor> (f: F._A -> F._B) -> F -> F._FB { |
|
return { $0.fmap(f) } |
|
} |
|
|
|
public protocol Monad : Functor { |
|
class func unit (f: _A) -> Self |
|
func bind (f : _A -> _FB) -> _FB |
|
func >>= (x: Self, f : _A -> _FB) -> _FB |
|
} |
|
|
|
/** |
|
Using these global binds usually crashes :( |
|
*/ |
|
infix operator >>= {associativity left} |
|
public func >>= <M: Monad> (x: M, f: M._A -> M._FB) -> M._FB { |
|
return x.bind(f) |
|
} |
|
public func bind <M: Monad> (x: M, f: M._A -> M._FB) -> M._FB { |
|
return x.bind(f) |
|
} |
|
|
|
/** |
|
Make Array a functor |
|
*/ |
|
extension Array : Functor { |
|
typealias _A = T |
|
typealias _B = Any |
|
typealias _FB = [_B] |
|
|
|
public func fmap <_B> (f: _A -> _B) -> [_B] { |
|
return self.map(f) |
|
} |
|
} |
|
|
|
/** |
|
Make Array a monad |
|
*/ |
|
extension Array : Monad { |
|
public static func unit (x: _A) -> [_A] { |
|
return [x] |
|
} |
|
|
|
public func bind <_B> (f: _A -> [_B]) -> [_B] { |
|
return self.map(f).reduce([], +) |
|
} |
|
} |
|
|
|
/** |
|
Make optional a functor |
|
*/ |
|
extension Optional : Functor { |
|
typealias _A = T |
|
typealias _B = Any |
|
typealias _FB = _B? |
|
|
|
public func fmap <_B> (f: _A -> _B) -> _B? { |
|
switch self { |
|
case let .Some(value): |
|
value |
|
return f(value) |
|
case .None: |
|
return .None |
|
} |
|
} |
|
} |
|
|
|
/** |
|
Make optional a monad |
|
*/ |
|
extension Optional : Monad { |
|
public static func unit (x: _A) -> _A? { |
|
return x |
|
} |
|
|
|
public func bind <_B> (f: _A -> _B?) -> _B? { |
|
switch self { |
|
case let .Some(value): |
|
return f(value) |
|
case .None: |
|
return .None |
|
} |
|
} |
|
} |
|
|
|
func square (x: Double) -> Double { |
|
return x * x |
|
} |
|
|
|
func invert (x: Double) -> Double? { |
|
if (x != 0.0) { |
|
return 1.0 / x |
|
} |
|
return nil |
|
} |
|
|
|
func squareRoot (x: Double) -> Double? { |
|
if (x < 0.0) { |
|
return nil |
|
} |
|
return sqrt(x) |
|
} |
|
|
|
func test (x: Double) -> String { |
|
return "test: \(x)" |
|
} |
|
|
|
/** |
|
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) |
|
// fmap(square)(xs) // crash! |
|
|
|
let optional2: Double? = 2 |
|
optional2.fmap(test) |
|
optional2.bind(squareRoot) |
|
// optional2 >>= squareRoot // crash! |
|
|
|
|
|
|
|
|
|
"done" |