2015-11-30 5 views
5

У меня есть следующий код:Haskell IO порядок выполнения

import Control.Monad (unless) 
import System.IO (isEOF, hFlush, stdout) 

main :: IO() 
main = unlessFinished $ do 
     putStr "$ " 
     hFlush stdout 
     getLine >>= putStrLn 
     main 
    where 
    unlessFinished action = isEOF >>= flip unless action 

Когда я скомпилировать и запустить этот код, он отображает курсор в начале заготовки линии и только после того, как я ударил [Enter] его выходы $ и все, что я написал.

Казалось бы, что getLine вызывается прежде, чем putStr "$ " даже хотя IO монадных гарантирует, что это действия, которые называются в порядке, они упорядочены в коде (или я так понимаю, что написано here). Так почему это работает неправильно?

+1

Кстати, я на самом деле не верю, пока я не попробовал запустить код самостоятельно. Затем я сказал «whaaaaa ...?!» вслух в моем кабинете. Хорошая работа, перегоняя ваш вопрос в такую ​​приятную, удобоваримую, удивительную форму! –

+0

Спасибо. Это было удивительно и для меня. На самом деле я начинал считать, что это не «ошибка» Хаскелла, а какая-то другая ошибка ядра/терминала/ОС, о которой я раньше не знал. :) – Sventimir

ответ

9

На самом деле, putStr и hFlush действия является выполняется до getLine действий - однако, isEOF в настоящее время выполняется, прежде чем либо, и она не возвращается, пока он не знает, является ли вход EOF или нет, то есть , пока вы не войдете в строку. Вы могли бы рассмотреть вопрос о переходе на isEOF направо перед getLine, как это:

main :: IO() 
main = do 
    putStr "$ " 
    hFlush stdout 
    unlessFinished $ do 
     getLine >>= putStrLn 
     main 
    where 
    unlessFinished action = isEOF >>= flip unless action 
+0

Поразительно простое объяснение! Мне уже интересно, как я не мог думать об этом сам. Я получаю, что у Хаскелла все еще есть больше подводных камней для меня, чем я ожидал. Большое спасибо. :) – Sventimir

 Смежные вопросы

  • Нет связанных вопросов^_^