swift实例解析Functor,Monad,Applicative

629 阅读2分钟

之前在网上看到几篇文章,但是一直都没看懂,直到看 Argo 的源码时,发现它里面也定义了这些,只不过是用 Enum 的,明白了许多。有兴趣的可以看看。

Functor,Monad,Applicative 都是指一种数据类型,只要该类型实现了其规定的方法,就可称为 Functor/Monad/Applicative。

Functor

haskell 中的定义:

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

实现了 (a -> b) -> f a -> f b 的类型称为 Functor,f 表示一种类型
假定将 (a->b) 叫 function,fa 是指在上下文中的值,好比 a 装在箱子里 Box(a)包起来了。可以用这样一个结构表示上下文。

//*************************************
// 均以Box为上下文
//*************************************
struct Box<T> {
    private var value: T
    init(_ value: T) {
        self.value = value
    }

    func unbox() -> T {
        return self.value
    }
}

// 实现了 (a -> b) -> f a -> f b的类型称为Functor,f表示一种类型
// ((a->b), Box(a)) -> Box(b)
// 表示函数第一个参数(a, b)是个函数f,第二个参数是fa(有上下文,这里指Box,取出a,需要unbox)
// 1.a = unbox a
// 2.b = f(a)
// 3.Box(b)
infix operator <^> { associativity left }
func <^><T, U>(f: T -> U, x: Box<T>) -> Box<U> {
    return x.map(f)
}

// 此时Box是个Functor
extension Box {
    func map<U>(f: T -> U) -> Box<U> {
        return Box<U>(f(unbox()))
    }
}

下图是比较形象的图片表示,(+3) 就相当于我们定义的函数 f,Box(2) 是在上下文中的值。取出 2,进行 + 3,然后再包装成 Box。

Functor 图片表示

Applicative

haskell 中的定义:

class (Functor f) => Applicative f where     
    pure :: a -> f a     
    (<*>) :: f (a -> b) -> f a -> f b 

实现了 f(a -> b) -> f a -> f b, a -> f a 的的类型称为 Applicative。
f(a -> b) 指在上下文中的函数,用 Box 可以表示为:BoxB>
fa 值在上下文中的值,Box(a)

// (Box(a->b), Box(a)) -> Box(b)
// 1.f = unbox function
// 2.a = unbox a
// 3.调用f(a)返回b,b=f(a)
// 4.Box(b)
infix operator <*> { associativity left }

func <*><T, U>(f: Box<T -> U>, x: Box<T>) -> Box<U> {
    return x.apply(f)
}

// a->Box(a)
func pure<T>(x: T) -> Box<T> {
    return Box(x)
}

// 此时Box是个Applicative
extension Box {
    func apply<U>(f: Box<T -> U>) -> Box<U> {
        let function = f.unbox()

        return map(function)
    }
}

图片解说:
function,2 均在 Box 中,需要取出,进行运算后,再放入 Box

Applicative 图片表示

Monad

haskell 中的定义:

class Monad m where 
    return :: a -> m a  
    (>>=) :: m a -> (a -> m b) -> m b 
    ...

实现了 m a -> (a -> m b) -> m b 的类型称为 Monad
m a 指上下文中的值,Box(a)
(a -> m b) 是一个函数,非上下文。传入 a,返回 Box(b)

// (Box(a), (a->Box(b))) -> Box(b)
// 表示第一个参数是在上下文中,函数(a, mb) 输入unbox的a值,输出Box
// 1.a = unbox a
// 2.Box(b) = f(a)
infix operator >>= { associativity left }
func >>=<T, U>(x: Box<T>, f: T -> Box<U>) -> Box<U> {
    return x.flatMap(f)
}

// 此时Box是个Monad
extension Box {
    func flatMap<U>(f: T -> Box<U>) -> Box<U> {
        let value = unbox()
        return f(value)
    }
}

Monad 图片表示

测试代码

// Functor Test
let box1 = Box<Int>(2)

// add 2
let function1: (Int -> String) = { x in
    return String(x + 2)
}

let r1 = function1 <^> box1
print(r1.unbox())

// Monad Test
let box2 = Box<Int>(3)
let function2: (Int -> Box<Int>) = { x in
    return Box<Int>((x + 2))
}

let r2 = box2 >>= function2
print(r2.unbox())

// Applicative Test
let box3 = Box<Int>(4)
let function3: Box<Int -> Int> = Box<Int -> Int>({ x in
    return x + 2
})

let r3 = function3 <*> box3
print(r3.unbox())