试图了解Monads.>>运营商

Tza*_*ama 11 monads haskell operator-keyword

我是haskell的新手,我正在通过LearnYouAHaskell学习.我只是无法理解(>>)运营商背后的原因.
默认实现是:

(>>) :: (Monad m) => m a -> m b -> m b  
m >> n = m >>= \_ -> n 
Run Code Online (Sandbox Code Playgroud)

这是(据我所知)忽略第一个值并返回第二个值.但是,从LearnYouAHaskell中的示例来看,这种情况发生了:

ghci>没什么>>只是3
没什么
ghci>只是3 >>什么都
没有

所以它不会忽略第一个值.然而,通过一些研究,我从这里找到了这个引用

>> function绑定运算符忽略其第一个操作的值,并仅作为整体结果返回其第二个操作的结果.

所以我对这个运算符的使用感到困惑,我想问两件事:

  1. 什么它实际上做什么?
  2. 什么时候有用?

Sib*_*ibi 15

>>函数仅忽略第一个值的结果,但忽略第一个值的副作用.要了解您的示例,请参阅如何Maybe定义Monad:

instance Monad Maybe where
  return = Just
  (Just x) >>= f = f x
  Nothing >>= _ = Nothing
Run Code Online (Sandbox Code Playgroud)

>>函数的定义如下:

m >> k      = m >>= \_ -> k
Run Code Online (Sandbox Code Playgroud)

Nothing >> _Nothing根据Maybemonad 的定义生成.在你的第二个例子中Just 3 >> Nothing,扩展到Just 3 >>= \_ -> Nothing并生成Nothing.为了举例说明它如何忽略第一个动作的值而不忽略副作用,请考虑以下示例:

?> print 3 >> print 4
3
4
Run Code Online (Sandbox Code Playgroud)

可以在上面的示例中看到的,尽管它忽略了结果的print 3()但它不会忽略它的副作用这是显示3在屏幕上.

>>一旦开始使用其他Haskell库,函数就会变得有用.偶尔使用它们的两个地方是处理Parsers(parsec,attoparsec)和Pipes库.


n. *_* m. 8

它忽略了第一个动作的价值,而不是动作本身.

Just 3 >> Just 5
Run Code Online (Sandbox Code Playgroud)

行动的价值Just 33.它在这\_ -> n部分被忽略了.总体结果是Just 5.

Just 3 >> Nothing
Run Code Online (Sandbox Code Playgroud)

行动的价值Just 33.它在这\_ -> n部分被忽略了.总体结果是Nothing.

Nothing >> Just 3
Run Code Online (Sandbox Code Playgroud)

该行动Nothing根本不会产生任何价值.它传递给>>=(或>>)右操作数的是什么?它没有!>>=对于Maybemonad的构建,如果左行动是Nothing,则根本不执行正确的动作,并且整体结果是Nothing.


mb1*_*b14 7

完成Sibi答案>>可以看作是;其他语言,如C或C++ ..

当你用C语言(或其他语言的同等学历)

的printf( "富"); 的printf( "条");

你显然打印foobar(副作用),但那些调用printf也有一个返回值,在我们的例子中是打印的长度,即3 3.你有没有想过这些数字会发生什么?他们被抛弃,因为在C,expr 1; exp 2,意思是

  • 评估expr1
  • 放弃了它的结果
  • 评估expr2

(那时候,你可以问你为什么编译器为了丢弃它的结果而无法评估expr1?由于副作用.在副作用的情况下printf是打印一些东西.你很少对返回的值本身感兴趣.)

因此;可以看作是一个运算符采用2表达式并返回一个新表达式.这与>>操作员的操作完全相同.

当你写作

 print "foo" >> print "bar"
Run Code Online (Sandbox Code Playgroud)

它完全等同于printf("foo");printf("bar")except(这是一个主要的区别)>>并不像;C中那样神奇.>>它是用户定义的运算符,可以为每种类型的Monad重新定义.这就是为什么Haskell程序员非常喜欢Monad的原因:简而言之,它允许你重新定义自己的行为;.

正如我们所见,在C中;只评估一个表达式并丢弃它的值.事实上,它有点复杂,因为它不是a break或a return.可能monad中的任何东西都可以被视为a break或a return.>>评估第一个表达式,如果是则停止Nothing.否则它会丢弃它的价值并继续.

你可以看到第一个例子C(我认为它是有效的C)

3; return
Run Code Online (Sandbox Code Playgroud)

return; 3
Run Code Online (Sandbox Code Playgroud)

第一个例子,计算3,丢弃其值并返回.第二个,直接回来.

回答你的问题when is it usefull?几乎所有的时候你使用IO,即使你很少看到它.

而不是写作

 print "foo" >> print "bar"
Run Code Online (Sandbox Code Playgroud)

Haskell提供了一个语法糖,它>>通过do-notation 转换(几乎)换行符,所以你会写

do
  print "foo"
  print "bar"
Run Code Online (Sandbox Code Playgroud)

这与前一版本完全相同(事实上,编号符号版本由编译器转换为前一版本).

它甚至也相当于(即使很少使用)

do print "foo"; print "bar"
Run Code Online (Sandbox Code Playgroud)

总而言之,>>可以看作是等同于;或换行是其他语言,区别在于它的确切含义取决于上下文(Monad正在采取行动). >>在一个可能的monad >>中与IO Monad不同.