swift實(shí)例解析Functor,Monad,Applicative

之前在網(wǎng)上看到幾篇文章,但是一直都沒(méi)看懂,直到看Argo的源碼時(shí),發(fā)現(xiàn)它里面也定義了這些,只不過(guò)是用Enum的,明白了許多。有興趣的可以看看。

Functor,Monad,Applicative都是指一種數(shù)據(jù)類型,只要該類型實(shí)現(xiàn)了其規(guī)定的方法,就可稱為Functor/Monad/Applicative。

Functor

haskell中的定義:

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

實(shí)現(xiàn)了 (a -> b) -> f a -> f b的類型稱為Functor,f表示一種類型
假定將(a->b)叫function,fa是指在上下文中的值,好比a裝在箱子里Box(a)包起來(lái)了??梢杂眠@樣一個(gè)結(jié)構(gòu)表示上下文。

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

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

// 實(shí)現(xiàn)了 (a -> b) -> f a -> f b的類型稱為Functor,f表示一種類型
// ((a->b), Box(a)) -> Box(b)
// 表示函數(shù)第一個(gè)參數(shù)(a, b)是個(gè)函數(shù)f,第二個(gè)參數(shù)是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)
}

// 此時(shí)Box是個(gè)Functor
extension Box {
    func map<U>(f: T -> U) -> Box<U> {
        return Box<U>(f(unbox()))
    }
}

下圖是比較形象的圖片表示,(+3)就相當(dāng)于我們定義的函數(shù)f,Box(2)是在上下文中的值。取出2,進(jìn)行+3,然后再包裝成Box。


Functor圖片表示

Applicative

haskell中的定義:

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

實(shí)現(xiàn)了 f(a -> b) -> f a -> f b, a -> f a的的類型稱為Applicative。
f(a -> b)指在上下文中的函數(shù),用Box可以表示為:Box<A->B>
fa值在上下文中的值,Box(a)

// (Box(a->b), Box(a)) -> Box(b)
// 1.f = unbox function
// 2.a = unbox a
// 3.調(diào)用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)
}

// 此時(shí)Box是個(gè)Applicative
extension Box {
    func apply<U>(f: Box<T -> U>) -> Box<U> {
        let function = f.unbox()

        return map(function)
    }
}

圖片解說(shuō):
function,2均在Box中,需要取出,進(jìn)行運(yùn)算后,再放入Box


Applicative圖片表示

Monad

haskell中的定義:

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

實(shí)現(xiàn)了 m a -> (a -> m b) -> m b的類型稱為Monad
m a指上下文中的值,Box(a)
(a -> m b)是一個(gè)函數(shù),非上下文。傳入a,返回Box(b)

// (Box(a), (a->Box(b))) -> Box(b)
// 表示第一個(gè)參數(shù)是在上下文中,函數(shù)(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)
}

// 此時(shí)Box是個(gè)Monad
extension Box {
    func flatMap<U>(f: T -> Box<U>) -> Box<U> {
        let value = unbox()
        return f(value)
    }
}
Monad圖片表示

測(cè)試代碼

// 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())
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容