[英]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.