Ленивая оценка и путаница с побочными эффектами ввода-вывода

Этот код (взят из Learn You A Haskell ):

main = do   putStr "Hey, "  
            putStr "I'm "  
            putStrLn "Andy!"  

очевидно desugars to

main =        putStr "Hey, " >>=  
       (\_ -> putStr "I'm "  >>= 
       (\_ -> putStrLn "Andy!"))

Который, как я понимаю его можно интерпретировать как высказывание «Чтобы поставитьStrLn« Энди! », мне сначала нужно поставитьStr« Я », а для этого мне сначала нужно поставитьStr« Эй »;

Я не согласен с этой интерпретацией , что раздражает, потому что компилятор явно этого не делает и оставляет меня в замешательстве.У меня проблема в том, что лямбды игнорируют свои аргументы, во время ленивых вычислений разве такие вещи не должны распознаваться и закрываться?

Также, конечно, привязка возвращает действие ввода-вывода, и когда это действие ввода-вывода попадает в главное, оно выполняется. Но что помешает ему напечатать «Эй, Энди! Я»? Я подозреваю, что это то, что делает привязка .

Кроме того, как действие ввода-вывода типа «IO ()» несет достаточно информации, чтобы позволить системе времени выполнения напечатать «Эй, я Энди!»? Чем этот IO () отличается от IO (), чем вывод «Hello World!» или записывает в файл?

Рассмотрим другую монаду со страницы википедии:

Sugared version:

do
  putStrLn "What is your name?"
  name <- getLine
  putStrLn ("Nice to meet you, " ++ name ++ "!")

Desugared version:

putStrLn "What is your name?" >>= 
   (\_ ->
      getLine >>=
         (\name ->
            putStrLn ("Nice to meet you, " ++ name ++ "!")))

Аналогичная история здесь.

Думаю, мне просто нужно увидеть определение связывания для ввода-вывода, и тогда все будет ясно. Еще кое-что, что могло бы сильно помочь, - это, если бы кто-то мог помочь мне пройти через то, как на самом деле оценивается программа, и определить точные моменты, когда возникают побочные эффекты.

6
задан TheIronKnuckle 22 November 2011 в 11:18
поделиться