種類* -> *
可能「構成」的幾種概念。更重要的是你可以「順序」組成它們。
newtype Compose f g x = Compose { getCompose :: f (g x) }
在這裏你可以看到Compose
有一種(* -> *) -> (* -> *) -> (* -> *)
很像仿函數中的任何好的構圖應該。
所以問題是:是否有類似以下的守法實例?
instance (Applicative f, Applicative g) => Applicative (Compose f g)
instance (Monad f, Monad g) => Monad (Compose f g)
而簡短的回答,爲什麼單子不構成以及applicatives是,雖然第一個實例可以被寫入第二不能。咱們試試吧!
我們可以熱身與Functor
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose fgx) = Compose (fmap (fmap f) fgx)
在這裏,我們看到,因爲我們可以fmap
的fmap
-ed f
,我們可以通過它經過層層f
和g
像我們需要。類似的遊戲的玩法是pure
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure a = Compose (pure (pure a))
同時(<*>)
出現棘手的,如果你仔細看,這是我們既fmap
和pure
使用完全相同的伎倆。
Compose fgf <*> Compose fgx = Compose ((<*>) <$> fgf <*> fgx)
在所有情況下,我們可以「穿越」的f
和g
層層推進,我們需要的正是運營商,我們可能希望。
但現在讓我們來看看Monad
。我不打算通過(>>=)
來定義Monad
,而是通過join
工作。要實現Monad
我們需要實現
join :: Compose f g (Compose f g x) -> Compose f g x
使用
join_f :: f (f x) -> f x -- and
join_g :: g (g x) -> g x
,或者,如果我們剝去newtype
噪音,我們需要
join :: f (g (f (g x))) -> f (g x)
在這一點上它可能是清楚的問題是---我們只知道如何連接連續層f
s或g
s,但在這裏我們看到他們交織。你會發現,我們需要一個可交換財產
class Commute f g where
commute :: g (f x) -> f (g x)
,現在我們可以實現
instance (Monad f, Monad g, Commute f g) => Monad (Compose f g)
與(在newtype
不可知)定義爲
join :: f (g (f (g x))) -> f (g x)
join fgfgx = fgx where
ffggx :: f (f (g (g x)))
ffggx = fmap commute fgfgx
fggx :: f (g (g x))
fggx = join_f ffggx
fgx :: f (g x)
fgx = fmap join_g fggx
join
所有這一切的結果是什麼? Applicative
s 總是Compose
,但是Monad
s Compose
只有當他們的層Commute
。
我們什麼時候可以commute
層?下面是一些例子
instance Commute ((->) x) ((->) y) where
commute = flip
instance Commute ((,) x) ((,) y) where
commute (y, (x, a)) = (x, (y, a))
instance Commute ((->) x) ((,) y) where
commute (y, xa) = \x -> (y, xa x)
-- instance Commute ((,) x) ((->) y) does not exist; try to write yourself!
--
-- OR:
-- It turns out that you need to somehow "travel back in time" to make it
-- work...
--
-- instance Commute ((,) x) ((->) y) where
-- commute yxa = (..., \y -> let (x, a) = yxa y in a)
由於這是「單子變壓器」部分下,相信所有這些意味着,'(應用型女,應用型克)=>應用型(C FG)',但它不是的情況下(Monad f,Monad g)=> Monad(C fg)',其中'數據C fga = C(f(ga))'。如果您想深入瞭解爲什麼會出現這種情況,那麼嘗試編寫後一個實例可能會說明問題。 – user2407038 2015-04-05 04:07:38
另請參見[具有示例顯示monads在組合下(有證明)沒有關閉?](http://stackoverflow.com/q/13034229/1333025) – 2015-04-05 05:13:32