動機
興趣
free monad
data Free f a where
Pure :: a -> Free f a
Impure :: f (Free f a) -> Free f a
eta :: Functor f => f a -> Free f a
eta = Impure . fmap Pure
這裡的f要是functor,所以free有兩種case
- 從一般數值生的Pure
- 把functor拔掉的Impure
另外有一個eta從functor生free
兩個動作
- 打包
- 把functor轉成free
free只剩下拆DS的功能,真的有做事的都回到fmap去
接著就能利用fmap,把applicative與monad做出來
instance Functor f => Functor (Free f) where
fmap f (Pure x) = Pure $ f x
fmap f (Impure m) = Impure $ fmap (fmap f) m
instance Functor f => Applicative (Free f) where
pure = Pure
Pure f <*> m = fmap f m
Impure f <*> m = Impure $ fmap (<*> m) f
instance Functor f => Monad (Free f) where
return = Pure
Pure a >>= k = k a
Impure m >>= k = Impure (fmap (>>= k) m)
freer monad
fmap的type是(a -> b) -> f a -> f b
如果有一個type直接把(a -> b)
與f a
先存好,是不是就直接是functor,同時利用free monad,就可以生出applicative與monad
所以有了Lan(freer monad)
data Lan g a where
Lan :: g x -> (x -> a) -> Lan g a
instance Functor (Lan g) where
fmap f (Lan gx h) = Lan gx (f . h)
lan :: g a -> Lan g a
lan ga = Lan ga id # return!!
吃 1. 被打包的值 2. 與轉type的函數 生freer(Lan) 這根本就是fmap
把free monad生出來
data FFree g a where
FPure :: a -> FFree g a
FImpure :: g x -> (x -> FFree g a) -> FFree g a
etaF :: g a -> FFree g a
etaF fa = FImpure fa FPure
剩下的部分
instance Functor (FFree g) where
fmap f (FPure x) = FPure (f x)
fmap f (FImpure u q) = FImpure u (fmap f . q)
instance Applicative (FFree g) where
pure = FPure
FPure f <*> x = fmap f x
FImpure u q <*> x = FImpure u ((<*> x) . q)
instance Monad (FFree g) where
return = FPure
FPure x >>= k = k x
FImpure u k' >>= k = FImpure u (k' >>> k)
看lan的fmap的實作會發現,根本只有函數合成而已!!
這裡可以注意Impure與FImpure Impure的目的是把被打包的值轉成Free 但FImpure本來就是吃被打包的值,那這裡怎麼模擬Impure? 把被打包的值的type換掉就好!!