在Haskell中列出monad的实例 - 为什么在bind-operation中使用concat?

时间:2018-02-07 12:57:12

标签: list function haskell monads

我在这里找到了一些问题: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值),其中早期函数的输出值是下一个函数的输入。正确?

返回列表实例。 fxs中的每个值使用map (*2) [1,2,3]函数。因此[2,4,6]会产生concat。这就是我想要的全部与否?我该如何在这里使用concat concat :: [[a]] -> [a] 的定义如下:

(>>=)

为什么我会在f - 函数中获得列表?是因为list是monad,我从该列表中获取每个值以将其提供给mapmap只获得单例输入?但是,如何迭代整个列表呢?选择每个值'在哪里?发生?如果{{1}}将整个列表xs作为输入(这是我如何理解的话),为什么我应该获得列表列表?

1 个答案:

答案 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类型的值。