在Haskell中,符号“>>”代表什么?

40

我正在阅读 Happstack 的 Guestbook 示例,注意到了 >> 符号,这是我在学习 Haskell 时的教科书中没有见过的(例如看看第23行)。 它是什么?

我在 Google 中找不到它,因为它完全忽略了 >>(Bing 并非如此,但显示出大量无关的结果)。


4
hoogle(以及下面提到的hayoo)是使用Haskell语法搜索的最佳方式。http://www.haskell.org/hoogle/?hoogle=%3E%3E - Keith
还有 Google Code Search,通常适用于这种情况,尽管对于这种特定情况可能不是最好的选择:http://google.com/codesearch?q=lang%3Ahaskell+%3E%3E&hl=en&btnG=Search+Code - Tyler
5个回答

47

在 do 表示法中

a >> b >> c >> d

等同于

do a
   b
   c
   d

(同时,a >>= (b >>= (c >>= d)) 类似于以下表达式的效果:

do r1 <- a
   r2 <- b r1
   r3 <- c r2
   d r3

由于Haskell函数通常是纯的,因此在上面的示例中评估a、b、c或d似乎没有意义,因此除非它包含副作用(IO等),否则Haskell不会执行它,这种推理正确吗? - Nearoo
2
@Nearoo 我不是该主题的专家,但我认为您忽略了a、b、c或d可能是纯的(单子),但仍然会抛出异常,从而影响程序流程,即使它们的返回值被忽略。 - voneiden
@Nearoo 不一定,根据a的结果,可能不会评估b、c和d,依此类推。考虑以下示例,使用Maybe和guard(来自Contol.Monad):((\x y -> guard (y /= 0) >> pure (x / y)) 42 0) :: Maybe Double - undefined

25

2
终极拳击冠军赛:Hoogle vs. Hayoo! - Thomas Eding
感谢这个难忘的URL!我一直通过http://hackage.haskell.org访问这个网站。 - Tim Robinson
考虑到 Haskell 的惰性求值,这是否导致完全不对 >> 左侧的函数进行求值? - Nearoo
@Nearoo:不,那些是操作(单子值),因此它们具有副作用。 - Seweryn Niemiec
@SewerynNiemiec 这个副作用点可能只在IO单子的情况下才有影响? - Hans
@Hans 不,我认为它对于每个单子都很重要。在 Haskell 中,单子的主要作用是表示一系列操作,这些操作在惰性评估下本来是不确定的。对于 Maybe 单子,Just 1 >> Nothing >> Just undefined 的结果是 Nothing;对于 EitherRight True >> Left "err" >> Left undefined 的结果是 Left "err";对于列表单子,[1,2,3] >> [] >> [1..] 的结果是 [];对于 Statelet f = get >>= put . succ in execState (f >> f >> f) 0 的结果是 3。因此,任何"状态"仍然可能会被更新,任何"异常"都会停止进一步的评估。 - lvsz

18

在 ghci 命令提示符下,您可以输入:

:info >>

然后得到像这样的结果:

class Monad m where
...
(>>) :: m a -> m b -> m b
...
        -- Defined in GHC.Base
infixl 1 >>

从那里开始,您只需查看源代码即可了解更多信息。

仅仅为了回答您的问题:

k >> f = k >>= \_ -> f

2
我现在感觉很愚蠢;我知道:i(info)命令,但我来自Java和PHP,仍在适应使用REPL进行所有操作。谢谢 - CharlesS
41
对于一个Haskell新手来说,这个回答是正确的,但几乎没有帮助。它为什么存在?有什么用处? +0。 (译注:此处的“+0”可能是计分系统中的得分或评级,根据上下文无法确定具体含义) - j_random_hacker
2
这对我来说已经足够了,我现在知道该去哪里搜索了;之前我毫无头绪。 - CharlesS

11

从Hackage上看,>> 的描述为:

"按顺序组合两个动作,舍弃第一个动作产生的任何值,就像命令式语言中的分号等序列操作符一样。"

我认为使用 >> 按顺序打印两个字符串是个很好的例子。在GHCI中输入以下命令:

putStr "Hello " >> putStrLn "World"

这相当于使用 do 符号的表示方法:

do putStr "Hello "
   putStrLn "World"


5
我并不是Haskell专家,但是>>是一个用于处理单子(monads)的运算符,在Haskell中可以实现命令式编程等许多不同功能。有许多关于单子的教程可供参考,这里有一个很好的教程
实际上,a >> b可以理解为“先做a,然后做b,并返回b的结果”。这与更常见的绑定运算符>>=类似。

10
回答“哪些是难以理解的事情”并不能澄清问题,我认为这会让读者感到失败。 - Don Stewart
很好。它们现在被称为“一个不寻常的特性”,而不是“难以理解的事情”。 - j_random_hacker
“调用一个函数并将结果传递给另一个函数”是一种不寻常的特性?好的…… - jrockway
1
你正在描述的可能是函数的简单组合,与单子无关,或者是 continuation,这对那些来自命令式编程世界的人来说也难以理解。抛开这些不谈:Haskell 中哪个主题产生了最多的教程和新手指南(通常形如“Monad 就像 X”)?为什么会这样? - j_random_hacker
1
从新手的角度来看,我发现这个答案很有启发性。对于那些刚接触函数式编程的人来说,单子绝对是一个学习曲线(也就是不寻常的特性)。 - vikingsteve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接