我在这里找到了一些问题:Redefining monad list instance。我现在正试图让我的脑袋缠绕着monad。但是我需要一些帮助,我不会将列表的实例定义作为monad。
这是我给monad的list-instance的定义:
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值m a
和一个函数,取值a
并生成一个作为参数给出的monadic值m b
。我饲料' a
m a
(a -> m b)
到函数m b
,因此得到一个monadic值(>>=)
。
用我自己的话说:bind-operator map f xs
允许链接monadic函数(返回monadic值),其中早期函数的输出值是下一个函数的输入。正确?
返回列表实例。 f
对xs
中的每个值使用map (*2) [1,2,3]
函数。因此[2,4,6]
会产生concat
。这就是我想要的全部与否?我该如何在这里使用concat
?
concat :: [[a]] -> [a]
的定义如下:
(>>=)
为什么我会在f
- 函数中获得列表?是因为list是monad,我从该列表中获取每个值以将其提供给map
和map
只获得单例输入?但是,如何迭代整个列表呢?选择每个值'在哪里?发生?如果{{1}}将整个列表xs作为输入(这是我如何理解的话),为什么我应该获得列表列表?
答案 0 :(得分:7)
如果
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]
的仿函数就足够了。
monad相对于仿函数的额外好处主要在于让f
产生monadic类型的值。