要完成 Sibi 回答 >> 在 C 或 C++ 等其他语言中可以看作是 ;..
当你用 C 语言(或其他语言的等效语言)做时
printf("foo");
printf("bar");
您显然打印了foobar(副作用),但那些对printf 的调用也有一个返回值,在我们的例子中是打印的长度,即3 3。你有没有想过这些数字会发生什么?
他们被抛弃了,因为在 C 中,expr 1; exp 2,表示
(此时,您可能会问自己,如果编译器要丢弃其结果,为什么还要费心评估 expr1 ?因为副作用。在printf 的情况下,副作用是打印一些东西。你很少对返回值本身感兴趣。)
所以; 可以看作是一个接受2 表达式并返回一个新表达式的运算符。这与>> 操作符所做的完全相同。
当你写作时
print "foo" >> print "bar"
它完全等同于printf("foo");printf("bar"),除了(这是一个主要区别)>> 不像 C 中的; 那样神奇。>> 它是一个用户定义的运算符,可以为每种类型的 Monad 重新定义。
这就是 Haskell 程序员如此钟爱 Monad 的原因:简而言之,它允许您重新定义自己的 ; 行为。
正如我们所见,在 C 语言中,; 只计算一个表达式并丢弃它的值。事实上,它有点复杂,因为它不是break 或return。 Maybe monad 中的 Nothing 可以被视为 break 或 return。 >> 计算第一个表达式,如果是 Nothing 则停止。否则它会丢弃它的值并继续。
你的第一个例子可以在C中看到(我认为它是有效的C)
3; return
和
return; 3
第一个例子,计算3,丢弃它的值并返回。
第二,直接返回。
回答你的问题when is it usefull?几乎所有时间都在使用 IO,即使您很少看到它。
而不是写
print "foo" >> print "bar"
Haskell 提供了一种语法糖,它通过 do-notation 将(几乎)换行符转换为>>,
所以你会写
do
print "foo"
print "bar"
与前一个版本严格等价(实际上do符号版本被编译器转换为前一个版本)。
它甚至也等价于(尽管很少使用)
do print "foo"; print "bar"
总而言之,>> 可以被视为等同于 ; 或换行符是其他语言,不同之处在于它的确切含义取决于 上下文(Monad 所作用的)。
Maybe monad 中的 >> 与 IO Monad 中的 >> 不同。