为什么`print <$>(print“ hello”)`打印“ hello”?

Kag*_*Umi 14 haskell

IO (IO ())同时计算(IO ())和时(),为什么

main :: IO (IO ())
main = print <$> (print "Hello, World!")
Run Code Online (Sandbox Code Playgroud)

打印

"Hello, World!"
Run Code Online (Sandbox Code Playgroud)

IO "Hello, World!" -- ??
"Hello, World!"
Run Code Online (Sandbox Code Playgroud)

chi*_*chi 21

main :: IO (IO ())
main = print <$> (print "Hello, World!")
Run Code Online (Sandbox Code Playgroud)

由于单子法则,等价于

main :: IO (IO ())
main = do 
   result <- print "Hello, World!"
   return (print result)
Run Code Online (Sandbox Code Playgroud)

现在,print始终返回()结果,因此整个代码等效于

main :: IO (IO ())
main = do 
   _ <- print "Hello, World!"
   return (print ())
Run Code Online (Sandbox Code Playgroud)

最后,main只需丢弃的结果。也就是说,最后一行可能会return (putStrLn "this is ignored")具有相同的效果。

因此,代码将只执行first print "Hello, World!"

我建议您始终定义main :: IO ()。Haskell允许我们声明main :: IO AnyTypeHere,但这(IMO)令人困惑。

我还建议您使用putStrLn,而不要print打印字符串,因为后者将引用并转义整个字符串。

  • 我会补充说,`f &lt;$&gt; a≡a &gt;&gt; = \ r-&gt; return $ fr`不仅是这种情况的特定事物,而且实际上适用于任何monad。 (5认同)