[英]List instance of monad in Haskell - why use concat in bind-operation?
我在這里找到了一些問題: 重新定義monad list實例 。 我現在正試圖把頭包裹在monad周圍。 但是我需要一些幫助,我不會將列表的實例定義作為monad。
這是我給monad的列表實例的定義:
instance Monad [] where
xs >>= f = concat $ map f xs
return x = [x]
fail _ = []
我不明白,為什么我需要在bind-function中使用concat。 這是我對(>>=)
定義:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
所以我有一些monadic值ma
和一個函數,取值a
並產生作為參數給出的monadic值mb
。 我“喂” a
從ma
到函數(a -> mb)
,從而得到一個monadic值mb
作為結果。 用我自己的話說:bind-operator (>>=)
允許鏈接monadic函數(返回monadic值),其中較早函數的輸出值是下一個函數的輸入。 對?
回到列表實例。 map f xs
在xs
每個值上使用函數f
。 因此, map (*2) [1,2,3]
導致[2,4,6]
。 這就是我想要的全部與否? 我該如何在這里使用concat
? concat
的定義如下:
concat :: [[a]] -> [a]
為什么我得到(>>=)
-function中的列表列表? 是因為list是monad而且我從該列表中獲取每個值以將其提供給f
並且map
只獲取singleton-inputs? 但是,如何迭代整個列表呢? “挑選每個價值”在哪里發生? 如果map
將整個列表xs作為輸入(這就是我理解它的原因)為什么我應該得到一個列表列表?
如果
x :: [a]
f :: a -> [b]
然后
map f :: [a] -> [[b]]
map f x :: [[b]]
所以,我們需要將后者扁平化為[b]
。 這是由concat
完成的。
請注意f
是如何生成列表的,因此map
將其轉換為列表列表。 這是至關重要的:如果f
沒有產生列表但是f :: a->b
,那么我們不需要concat
- 我們甚至不需要monad,因為提供fmap=map :: (a->b) -> [a] -> [b]
函數) fmap=map :: (a->b) -> [a] -> [b]
就足夠了。
monad相對於functor的額外好處主要在於讓f
產生monadic類型的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.