繁体   English   中英

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

[英]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 我“喂” ama到函数(a -> mb) ,从而得到一个monadic值mb作为结果。 用我自己的话说:bind-operator (>>=)允许链接monadic函数(返回monadic值),其中较早函数的输出值是下一个函数的输入。 对?

回到列表实例。 map f xsxs每个值上使用函数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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM