*Main> getLine >> getLine
foo
bar
"bar"
*Main> putStrLn "foo" >> putStrLn "bar"
foo
bar
(>>)是否对所有实例都具有一致的含义?
但是这个怎么样:
*Main> [1,2] >> [1,2]
[1,2,1,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
。所以:
它“运行”monadic操作x
(类型为m a
),并忽略结果中a
类型的实际值,但>>=
可以使用其“形状”或副作用(在List
案例中,它是元素的数量;在Maybe
案例中,无论您是Just
还是Nothing
;对于IO
,这是副作用;等等;
>>=
的每种类型都很容易拥有>>
;它只是Monad
的方法,而不是单独的函数,因为对于某些类型,您可以比默认版本更有效地实现它,但它必须始终给出相同的结果。