[英]List instance of monad in Haskell - why use concat in bind-operation?
I found some question here: Redefining monad list instance . 我在这里找到了一些问题: 重新定义monad list实例 。 I'm currently trying to get my head wrapped around monads.
我现在正试图把头包裹在monad周围。 But I need some help here, I don't get the instance-definition of lists as monads.
但是我需要一些帮助,我不会将列表的实例定义作为monad。
This is my given definition of a list-instance for a monad: 这是我给monad的列表实例的定义:
instance Monad [] where
xs >>= f = concat $ map f xs
return x = [x]
fail _ = []
I dont understand, why I need concat in the bind-function. 我不明白,为什么我需要在bind-function中使用concat。 This is my definition of
(>>=)
: 这是我对
(>>=)
定义:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
So I have some monadic value ma
and a function, taking a value a
and producing a monadic value mb
given as parameters. 所以我有一些monadic值
ma
和一个函数,取值a
并产生作为参数给出的monadic值mb
。 I 'feed' a
from ma
into the function (a -> mb)
and thus get a monadic value mb
as a result. 我“喂”
a
从ma
到函数(a -> mb)
,从而得到一个monadic值mb
作为结果。 In my own words: The bind-operator (>>=)
allows to chain monadic functions (returning monadic values) where the value of the output of the earlier function is the input for the next function. 用我自己的话说:bind-operator
(>>=)
允许链接monadic函数(返回monadic值),其中较早函数的输出值是下一个函数的输入。 Right? 对?
Back to the list-instance. 回到列表实例。
map f xs
uses the function f
on every value in xs
. map f xs
在xs
每个值上使用函数f
。 So map (*2) [1,2,3]
results in [2,4,6]
. 因此,
map (*2) [1,2,3]
导致[2,4,6]
。 And that's all I wanted here or not? 这就是我想要的全部与否? How should I use
concat
here? 我该如何在这里使用
concat
? The definition of concat
is as follows: concat
的定义如下:
concat :: [[a]] -> [a]
Why do I get a list of lists in the (>>=)
-function? 为什么我得到
(>>=)
-function中的列表列表? Is it because list is the monad and I take every single value from that list to feed it to f
and map
just gets singleton-inputs? 是因为list是monad而且我从该列表中获取每个值以将其提供给
f
并且map
只获取singleton-inputs? But how do I iterate over the whole list then? 但是,如何迭代整个列表呢? Where does the 'picking each value' happen?
“挑选每个价值”在哪里发生? And if
map
takes the whole list xs as input (that's how I understand it) why should I get a list of lists? 如果
map
将整个列表xs作为输入(这就是我理解它的原因)为什么我应该得到一个列表列表?
If 如果
x :: [a]
f :: a -> [b]
then 然后
map f :: [a] -> [[b]]
map f x :: [[b]]
so, we need to flatten the latter into [b]
. 所以,我们需要将后者扁平化为
[b]
。 This is done by concat
. 这是由
concat
完成的。
Note how f
was already producing a list, so map
makes that into a list-of-lists. 请注意
f
是如何生成列表的,因此map
将其转换为列表列表。 This is crucial: if f
was not producing a list but were f :: a->b
, then we don't need concat
-- we don't even need a monad, since a functor providing fmap=map :: (a->b) -> [a] -> [b]
would be enough. 这是至关重要的:如果
f
没有产生列表但是f :: a->b
,那么我们不需要concat
- 我们甚至不需要monad,因为提供fmap=map :: (a->b) -> [a] -> [b]
函数) fmap=map :: (a->b) -> [a] -> [b]
就足够了。
The added benefit of a monad over a functor mainly lies in letting f
produce a value in a monadic type. monad相对于functor的额外好处主要在于让
f
产生monadic类型的值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.