fmap putStrLn getLine不执行IO

时间:2014-07-29 09:37:24

标签: haskell

实际上,标题说了这一切。我无法理解为什么以下代码实际上没有打印" Hello World"与>>=所做的相反。

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 M​​onad有效的IO时,为什么编译器不会发出警告?

1 个答案:

答案 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