在列表 monad 中使用 return 与不使用 return [英] Using return vs. not using return in the list monad

查看:21
本文介绍了在列表 monad 中使用 return 与不使用 return的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始了我的 Grand Haskell Crusade (GHC :) ) 并且我对 monad 和 IO 函数有点困惑.谁能简单地解释一下这两个函数之间的区别是什么?

I started my Grand Haskell Crusade (GHC :) ) and I am a bit confused with monads and IO functions. Could anyone explain simply what is the difference between those two functions?

f1 = do x <- [1,2]
        [x, x+1] -- this is monad, right?

f2 = do x <- [1,2]
        return [x, x+1]

结果是:

*Main> f1
[1,2,2,3]

*Main> f2
[[1,2],[2,3]]

推荐答案

这里的其他答案是正确的,但我想知道它们是否不是您所需要的......我会尽量保持简单,只有两点:

The other answers here are correct, but I wonder if they're not quite what you need... I'll try to keep this as simple as possible, just two points:

第 1 点.return 在 Haskell 语言中并不是什么特别的东西.它不是关键字,也不是其他事物的语法糖.它只是一个属于 Monad 类型类的函数.它的签名很简单:

Point 1. return is not a special thing in the Haskell language. It's not a keyword, and it's not syntactic sugar for something else. It's just a function that's part of the Monad typeclass. Its signature is simply:

return :: a -> m a

其中 m 是我们当时正在谈论的任何 monad.它需要一个纯"值并将其塞入您的 monad 中.(顺便说一句,还有一个函数叫做 pure 基本上是 return 的同义词...我更喜欢它,因为名字更明显!)无论如何,如果 m 是列表 monad,然后 return 具有这种类型:

where m is whichever monad we're talking about at the time. It takes a "pure" value and jams it into your monad. (Incidentally, there's another function called pure that's basically a synonym for return... I like it better because the name is more obvious!) Anyway, if m is the list monad, then return has this type:

return :: a -> [a]

如果有帮助,您可以考虑类型同义词 type List a = [a],这可能会使 List 是我们的东西变得更加明显重新替换m.无论如何,如果您要自己实现 return,那么实现它的唯一合理方法是获取一些值(任何类型的 a)并将其粘贴在单独列出:

If it helps, you could think of the type synonym type List a = [a], which might make it slightly more obvious that List is the thing we're substituting for m. Anyway, if you were going to implement return yourself, the only reasonable way you'd implement it is by taking some value (of whatever type a) and sticking it in a list by itself:

return a = [a]

所以我可以在列表monad中说return 1,然后我会得到[1].我同样可以说 return [1, 2, 3] 并且我会得到 [[[1, 2, 3]].

So I can say return 1 in the list monad, and I'll get [1]. I can likewise say return [1, 2, 3] and I'll get [[1, 2, 3]].

第 2 点.IO 是一个 monad,但并非所有的 monad 都是 IO. 许多 Haskell 教程似乎主要将这两个主题混为一谈历史原因(顺便说一句,同样令人困惑的历史原因导致 return 名称如此糟糕).听起来您对此可能有一些(可以理解的)困惑.

Point 2. IO is a monad, but not all monads are IO. Many Haskell tutorials seem to conflate the two topics largely for historical reasons (incidentally, the same confusing historical reasons that led to return being so poorly named). It sounds like you might have some (understandable) confusion around that.

在您的代码中,您在列表 monad 中,因为您编写了 do x <- [1, 2].例如,如果您编写了 do x <- getLine,那么您将处于 IO monad 中(因为 getLine 返回 IO 字符串).无论如何,您在列表 monad 中,因此您将获得上述 return 列表的定义.您还可以得到 >>= 的列表定义,它只是(翻转版本)concatMap,定义为:

In your code, you're in the list monad because you wrote do x <- [1, 2]. If instead you had written do x <- getLine for example, you'd be in the IO monad (because getLine returns IO String). Anyway, you're in the list monad, so you get list's definition of return described above. You also get list's definition of >>=, which is just (a flipped version of) concatMap, defined as:

concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f xs = concat (map f xs)

其他已发布的答案几乎涵盖了此处:) 我知道我没有直接回答您的问题,但我希望这两点能够解决您可能会感到困惑的基本问题.

The other posted answers pretty much have it covered from here :) I know I didn't answer your question directly, but I'm hoping these two points instead addressed the fundamental things you might have found confusing.

这篇关于在列表 monad 中使用 return 与不使用 return的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆