在列表 monad 中使用 return 与不使用 return [英] Using return vs. not using return in the list monad
问题描述
我开始了我的 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屋!