gpt4 book ai didi

Haskell 中 monad 的列表实例 - 为什么在绑定(bind)操作中使用 concat?

转载 作者:行者123 更新时间:2023-12-02 18:21:01 25 4
gpt4 key购买 nike

我在这里发现了一些问题:Redefining monad list instance 。我目前正试图让我的头脑集中在 monad 上。但我在这里需要一些帮助,我没有将列表的实例定义作为单子(monad)。

这是我给单子(monad)的列表实例的定义:

    instance Monad [] where
xs >>= f = concat $ map f xs
return x = [x]
fail _ = []

我不明白,为什么我需要在绑定(bind)函数中连接。这是我对 (>>=) 的定义:

    (>>=) :: Monad m => m a -> (a -> m b) -> m b

所以我有一些一元值 m a 和一个函数,获取一个值 a 并生成一个作为参数给出的一元值 m b 。我将 m a 中的 a 馈送到函数 (a -> m b) 中,从而获得一元值 m b > 结果。用我自己的话说:绑定(bind)运算符 (>>=) 允许链接一元函数(返回一元值),其中前一个函数的输出值是下一个函数的输入。对吗?

返回列表实例。 map f xsxs 中的每个值使用函数 f。因此,map (*2) [1,2,3] 结果为[2,4,6]。这就是我想要的一切吗?我应该如何在这里使用 concatconcat的定义如下:

    concat :: [[a]] -> [a]

为什么我会在 (>>=) 函数中获得列表列表?是因为 list 是 monad 并且我从该列表中获取每个值并将其提供给 fmap 只是获取单例输入?但是我该如何迭代整个列表呢? “选择每个值”在哪里发生?如果 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] 的仿函数就足够了。

单子(monad)相对于仿函数的额外好处主要在于让 f 生成单子(monad)类型的值。

关于Haskell 中 monad 的列表实例 - 为什么在绑定(bind)操作中使用 concat?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48664418/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com