コマンドライン Haskell プログラムを次のように機能させたいと思います: プログラムはユーザー入力を待ち、
- ユーザーが何かを入力し、「Enter」を押します
- Haskell は入力を処理し、標準出力に結果を表示します
- Haskell は次のユーザー入力を待ちます
- 入力がない場合、ユーザーは Ctrl+D でプログラムを終了します
getContents を試してみました。ただし、getContents は、ユーザーがすべての行を入力するのを待ってから処理します。
コマンドライン Haskell プログラムを次のように機能させたいと思います: プログラムはユーザー入力を待ち、
getContents を試してみました。ただし、getContents は、ユーザーがすべての行を入力するのを待ってから処理します。
ここで多くの混乱が起こっています。物事を片付けようとしましょう。
getContents を試してみました。ただし、getContents は、ユーザーがすべての行を入力するのを待ってから処理します。
ここで最も可能性が高いのは、プログラムをコンパイルした後、出力のデフォルトのバッファリングがブロック バッファリングであることに気付かなかったことです。これは簡単に修正できます。
f line = putStrLn ("Hi, " ++ line ++ "!")
main = do
hSetBuffering stdout LineBuffering -- or use NoBuffering
putStrLn "Enter some names."
input <- getContents
mapM_ f (lines input)
NoBuffering
ユーザー入力の各行の後に行全体 (改行を含む) を印刷する予定がない場合に使用する必要があります。
より正確な回答を得るには、あなたが試したがうまくいかなかったコードを確認する必要があります。
Q: しかし、最初の試行で、「interact show」を使用しましたが、機能しません。なぜなのかご存知ですか?
A: 入力全体が使い果たされるまで、show は出力を返さないためです。
この答えは完全に正しくありません。本当の答えは、show
改行のない文字列を生成することです! (ただし、入力が 1 行以上の長さの場合、文字シーケンス['\\','\n']
が表示されることがあります。) したがって、 for 、 oninteract show
を実際に使用する必要があります。たとえば、これを使用する場合:NoBuffering
stdout
main = do
hSetBuffering stdout NoBuffering
interact show
...プログラムは、各行の後にもう少し出力を出力します。stdin
のバッファリングをNoBuffering
(デフォルトの ではなくLineBuffering
) に設定することもできます。これは、各キーストローク後に実際により多くの出力を生成できるほど十分に生産的であるためですshow
。
You can try using the interact
function. It takes a function of type String -> String
and converts it into an action that reads stdin, passes it continuously to the function, and writes the string that the function returns to stdout. If you take care not to overconsume the input string, you will get the behavior that you requested.
これにより、 を使用して発生した遅延入出力の問題が回避されますinteract
。
(を使用しない場合isEOF
、Ctrl+D を押すと例外がスローされます。)
import Control.Monad (unless)
import System.IO (isEOF)
processEachLine :: (String -> IO a) -> IO ()
processEachLine k = do
finished <- isEOF
unless finished $ do
k =<< getLine
processEachLine k
ここでは、k
関数が必要な出力自体を出力すると仮定します。出力を純粋processEachLine
に印刷するように変更するのは簡単です。k