【发布时间】:2012-01-03 18:50:00
【问题描述】:
此代码(取自Learn You A Haskell):
main = do putStr "Hey, "
putStr "I'm "
putStrLn "Andy!"
显然去糖了
main = putStr "Hey, " >>=
(\_ -> putStr "I'm " >>=
(\_ -> putStrLn "Andy!"))
据我所知,它可以解释为“为了 putStrLn "Andy!" 我首先需要 putStr "I'm ",为此我首先需要 putStr "Hey,";
我不同意这种解释,这很烦人,因为编译器显然不这样做,这让我感到困惑。我遇到的问题是 lambdas 忽略了他们的论点,在惰性评估期间,这种事情不应该被识别和短路吗?
另外,当然,绑定返回一个 IO 操作,当该 IO 操作落入 main 时,它会被执行。但是如何阻止它打印“嘿,安迪!我是”?我怀疑这是绑定在做什么。
此外,“IO ()”类型的 IO 操作如何携带足够的信息以允许运行时系统打印“嘿,我是安迪!”? IO () 与 IO () 相比打印“Hello World!”有何不同?还是写入文件?
考虑另一个,来自 wikipedia 页面的 monad:
加糖版:
do
putStrLn "What is your name?"
name <- getLine
putStrLn ("Nice to meet you, " ++ name ++ "!")
脱糖版本:
putStrLn "What is your name?" >>=
(\_ ->
getLine >>=
(\name ->
putStrLn ("Nice to meet you, " ++ name ++ "!")))
这里有类似的故事。
我想我只需要查看 IO 绑定的定义,然后就一切都清楚了。如果有人可以帮助我逐步了解程序的实际评估方式并确定副作用发生的确切时刻,那么其他会很有帮助的事情。
【问题讨论】:
-
“lambda 忽略了他们的论点,在惰性求值期间,这种事情不应该被识别和短路吗?”你打赌!
(>>=)的第二个参数在这里是一个特别惰性的函数,但(>>=)函数本身并不惰性。
标签: haskell functional-programming lazy-evaluation side-effects