为什么:getLine和putStrLn表现不同?

时间:2015-12-25 10:32:12

标签: haskell

*Main> getLine >> getLine
foo
bar
"bar"
*Main> putStrLn "foo" >> putStrLn "bar"
foo
bar

(>>)是否对所有实例都具有一致的含义?

但是这个怎么样:

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

我只想得到(>>)所有实例的共同点。如果它只是放弃了之前的结果,我认为每种类型都可以轻松地使用这种方法。

2 个答案:

答案 0 :(得分:4)

getLine具有签名IO String,而putStrLn具有签名String -> IO ()。因此,当>>getLine一起使用时,结果的String部分将被丢弃,您只能看到第二个getLine的结果。另一方面,对于putStrLn,结果实际上是(),因此当丢弃该值时,您不会看到差异,因为该值已经打印到输出中。

答案 1 :(得分:2)

  

我只想得到(>>)所有实例的共同点。如果它只是放弃了之前的结果,我认为每种类型都可以轻松地使用这种方法。

如果您查看签名:(>>) :: m a -> m b -> m b,您可以认为它已实现为_ >> x = x。但是你已经看到它必须与列表示例有所不同。实际上,它实现为x >> y = x >>= \_ -> y。所以:

  1. 它“运行”monadic操作x(类型为m a),并忽略结果中a类型的实际值,但>>=可以使用其“形状”或副作用(在List案例中,它是元素的数量;在Maybe案例中,无论您是Just还是Nothing;对于IO,这是副作用;等等;

  2. >>=的每种类型都很容易拥有>>;它只是Monad的方法,而不是单独的函数,因为对于某些类型,您可以比默认版本更有效地实现它,但它必须始终给出相同的结果。