Monads在理論上被稱爲函子的一個子集,特別適用於函子,儘管它在Haskell的類型系統中沒有被指出。如何顯示monad是一個仿函數和一個應用函子?
知道了,給定一個單子,並立足於return
和bind
,如何:
- 獲得
fmap
, - 獲得
<*>
?
Monads在理論上被稱爲函子的一個子集,特別適用於函子,儘管它在Haskell的類型系統中沒有被指出。如何顯示monad是一個仿函數和一個應用函子?
知道了,給定一個單子,並立足於return
和bind
,如何:
fmap
,<*>
?那麼,fmap
只是(a -> b) -> f a -> f b
,即我們想要用一個純函數來轉換monadic動作的結果。這很簡單,用做記號寫:
fmap f m = do
a <- m
return (f a)
,或者寫着 「原始」:
fmap f m = m >>= \a -> return (f a)
這可作爲Control.Monad.liftM
。
pure :: a -> f a
當然是return
。 (<*>) :: f (a -> b) -> f a -> f b
有點棘手。我們有一個動作返回一個函數,一個動作返回它的參數,我們想要一個返回結果的動作。在再做記號:
mf <*> mx = do
f <- mf
x <- mx
return (f x)
或者脫:
mf <*> mx =
mf >>= \f ->
mx >>= \x ->
return (f x)
田田!這可作爲Control.Monad.ap
,所以我們可以給的Functor
和Applicative
一個完整的實例任何單子M
如下:
instance Functor M where
fmap = liftM
instance Applicative M where
pure = return
(<*>) = ap
理想情況下,我們就可以直接在Monad
指定這些實現,以減輕負擔爲每個monad定義單獨的實例,例如this proposal。如果發生這種情況,將Applicative
設爲Monad
的超類並不存在真正的障礙,因爲它可以確保它不會破壞任何現有的代碼。另一方面,這意味着爲給定的Monad
定義Functor
和Applicative
實例所涉及的樣板很少,所以很容易成爲「好公民」(並且應該爲任何monad定義這樣的實例)。
這個答案缺少一個重要的部分:證明如果一個給定的'Monad'實例'm'確實滿足Monad定律,那麼你提供給'fmap','pure'和[(<*>)'的單子定義'服從法師和適用法律。 Haskell強制執行的是類型檢查。 – 2012-02-03 02:04:22