>>=
所做的相反。
main = fmap putStrLn getLine
目前,这是我的推理线,请检查它是否有任何谬误。
如果我们将fmap
与>>=
(>>=) :: Monad m => m a -> (a -> m b) -> m b
fmap :: Functor f => (a -> b) -> f a -> f b
在绑定,上下文或IO术语中,#34; World"除了类型之外,第一个m
和第二个m
完全不同。 (a -> m b)
基本上重新创造了一个新的世界"。在Functor中不是这样,上下文f
是相同的,因此副作用是不可能的。
现在,如果确实如此,当我们尝试fmap
对现有IO Monad有效的IO时,为什么编译器不会发出警告?
答案 0 :(得分:13)
你几乎就在那里。 fmap putStrLn
的类型是什么?
putStrLn :: String -> IO ()
fmap :: Functor f => (a -> b) -> f a -> f b
fmap putStrLn :: Functor f => f String -> f (IO ())
结果fmap putStrLn getLine
将是IO (IO ())
,即IO动作,其中包含另一个 IO动作。毕竟不需要警告 * ,这可能就是你想要的。编译器无法确定您是否需要m (m a)
或m a
。
这实际上是monad的力量,它有一个操作可以让你加入这些行动:
join :: Monad m => m (m a) -> m a
-- join x = x >>= id
*除了可能缺少的类型签名。您可以告诉GHC警告您-fwarn-missing-signatures
的人。见warnings and sanity-checking。