fmap putStrLn getLine不执行IO [英] fmap putStrLn getLine does not perform IO
问题描述
实际上,标题说明了一切.我不明白为什么下面的代码与>> =
的行为相反,实际上并未打印"Hello World".
The title said it all, actually. I can't understand why this following code does not actually print "Hello World" as opposed of what >>=
does.
main = fmap putStrLn getLine
目前,这是我的推理路线,请检查其是否有谬误.
Currently, here is my line of reasoning, please check if it has any fallacy.
如果我们将 fmap
与>> =
(>>=) :: Monad m => m a -> (a -> m b) -> m b
fmap :: Functor f => (a -> b) -> f a -> f b
在绑定中,上下文或以IO术语世界"而言,第一个 m
和第二个 m
在类型上完全不同.(a-> m b)
本质上重新创建了一个新的世界".在Functor中并非如此,上下文 f
是相同的,因此没有副作用.
In bind, the context, or in IO terms "World" the first m
and the second m
is entirely different aside of the types. (a -> m b)
essentially recreates a new "World". This is not true in Functor, the context f
are the same hence side effects are impossible.
现在,如果确实如此,当我们尝试将有效的IO fmap
到现有IO Monad时,编译器为什么不给出警告?
Now, if that's indeed the case, why doesn't the compiler gives a warning when we try to fmap
an effectful IO to an existing IO Monad?
推荐答案
您快到了. fmap putStrLn
是什么类型?
You're almost there. What is the type of 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
.
And as a result fmap putStrLn getLine
will be IO (IO ())
, that is, an IO action, which contains another IO action. There's no need for a warning*, after all, this could be what you intended. The compiler cannot determine whether you wanted m (m a)
or m a
.
这实际上是单子的力量,它具有使您能够加入这些动作的操作:
That's actually the power of a monad, it has an operation which enables you to join those actions:
join :: Monad m => m (m a) -> m a
-- join x = x >>= id
*,但可能缺少类型签名.您可以告诉GHC对具有 -fwarn-missing-signatures
的用户发出警告.请参阅警告和健全性检查.
* except maybe for the missing type signature. You can tell GHC to warn you about those with -fwarn-missing-signatures
. See warnings and sanity-checking.
这篇关于fmap putStrLn getLine不执行IO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!