2015-11-30 16 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がさえ、それの行為は、彼らはコード内で配列を決定している(またはので、私はhere書かれているかを理解)の順序で呼び出されていることIOモナドを保証してもputStr "$ "前に呼び出されることと思われます。なぜそれが正しく動作しないのですか?実際

+1

ちなみに、私はコードを自分で実行してみましたまで、私は実際にあなたを信じていませんでした。それから私は実際に "whaaaaa ...?"と言った。大声で私の部屋で。あなたの質問を素晴らしい、消化し易い、驚くべき形に蒸した素晴らしい仕事! –

+0

ありがとうございます。私にとっても驚きました。実際に私は結局ハスケルの「失敗」ではないと信じ始めていましたが、私が以前は知らなかった他のシェル/ターミナル/ OSの落とし穴です。 :) – Sventimir

答えて

9

putStrhFlushアクションgetLineアクションの前に実行されてている - しかし、isEOFはどちらかの前に実行されている、そしてそれは入力がEOFであるかどうかを知るまで、それは戻らない、つまりあなたが行を入力するまで。あなたはこのように、getLine前に右にisEOFを動かす考えるかもしれない:

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

驚くほど簡単な説明!私はすでに自分がどう考えていないのだろうかと思っています。私は、ハスケルはまだ私が予想していたよりも落とし穴が多いことが分かった。どうもありがとう。 :) – Sventimir