2016-12-14 86 views
0

我正在處理函子,應用程序和單子。在自定義數據類型上定義和使用monadic結構?

這些例子只是爲了說明的基礎知識:

data User a = Age a deriving (Show, Eq, Ord) 

函子(施加非上下文功能到單一上下文數據類型):

instance Functor User where 
    fmap f (Age a) = Age (f a) 

functorFunction :: Int -> Int 
functorFunction e = e + 1 

main = do 
print $ fmap functorFunction (Age 22) 

應用型(施加簡單的功能,以多個上下文數據類型):

instance Applicative User where 
    pure a = Age a 
    (<*>) (Age a) = fmap a 

applicativeFunction :: Int -> Int -> Int 
applicativeFunction e1 e2 = e1 + e2 

main = do 
    print $ pure (applicativeFunction) <*> (Age 44) <*> (Age 65) 

我經歷learnyouahaskell而一直沒能找到

1)如何定義我的「用戶」型單子結構簡單的解釋,和2)什麼功能的單子提供與,例如,一個應用功能?

+8

您的用戶類型同構於[Identity]函子(https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Identity.html#t:Identity )。看看[其源代碼](https://hackage.haskell.org/package/base-4.9.0.0/docs/src/Data.Functor.Identity.html#line-97) –

+2

關於2,請參見[這個](http://stackoverflow.com/a/38719766/3072788)。 – Alec

+3

或[this](http://stackoverflow.com/questions/17409260/what-advantage-does-monad-give-us-over-an-applicative)。 – arrowd

回答

2

1)如何定義一個單子結構爲我的「用戶」型

(初步注:瞭解你一個Haskell早Applicative成爲Monad的超出於這個原因,不像。書中建議,與最新版本的GHC的沒有必要實施return的 - 。在默認情況下,它是一樣的pure既如此,我會直接跳轉到(>>=)

關於與方法的一個好處非常一般類型如(>>=) ...

(>>=) :: Monad m => m a -> (a -> m b) -> m b 

...是,他們是如此普遍,存在實現他們的一些合理的方法 - 往往只有一個。如果我們專注(>>=)你的類型,我們可以得到:

(>>=) @User :: User a -> (a -> User b) -> User b 

所以(>>=)應該採取User aa -> User b並用它們來產生User b。鑑於該函數的值爲a,首先要嘗試查找要傳遞給它的值a。我們確實有這樣的值:在一個由Age構造在User a值包裹:

instance Monad User where 
    (Age a) >>= f = f a 

需要編寫好良心Monad情況下,我們應檢查其是否遵循單子法律:

return a >>= f = f a 

m >>= return = m 

(m >>= f) >>= g = m >>= (\x -> f x >>= g) 

,可以用(你最喜歡的當量)的筆和紙來完成:

return a >>= f = f a 
Age a >>= f = f a 
f a = f a 

m >>= return = m 
Age a >>= return = Age a -- [*] 
Age a >>= Age = Age a 
Age a = Age a 

-- [*]: Both here and in the next law, we can replace 'm' by 'Age a' 
--  because there is just one constructor. If there were more 
--  (as in e.g. data Maybe a = Nothing | Just a), we would have 
--  to check the law holds for all constructors. 

(m >>= f) >>= g = m >>= (\x -> f x >>= g) 
(Age a >>= f) >>= g = Age a >>= (\x -> f x >>= g) 
f a >>= g = (\x -> f x >>= g) a 
f a >>= g = f a >>= g 

2)monad提供的功能與應用函子相比如何?

這裏我將把它留給the question arrowd suggested。我只會注意到,你的例子並沒有給你足夠的認識,因爲User上下文過於簡單,不能讓你做任何有趣的事情(如Benjamin Hodgson指出的那樣,它與Identity同構,虛擬仿函數)。 Maybe,這是被接受的問題的答案使用,是更具說明性。