6

コマンドライン Haskell プログラムを次のように機能させたいと思います: プログラムはユーザー入力を待ち、

  1. ユーザーが何かを入力し、「Enter」を押します
  2. Haskell は入力を処理し、標準出力に結果を表示します
  3. Haskell は次のユーザー入力を待ちます
  4. 入力がない場合、ユーザーは Ctrl+D でプログラムを終了します

getContents を試してみました。ただし、getContents は、ユーザーがすべての行を入力するのを待ってから処理します。

4

3 に答える 3

9

ここで多くの混乱が起こっています。物事を片付けようとしましょう。

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を実際に使用する必要があります。たとえば、これを使用する場合:NoBufferingstdout

main = do
    hSetBuffering stdout NoBuffering
    interact show

...プログラムは、各行の後にもう少し出力を出力します。stdinのバッファリングをNoBuffering(デフォルトの ではなくLineBuffering) に設定することもできます。これは、各キーストローク後に実際により多くの出力を生成できるほど十分に生産的であるためですshow

于 2012-04-17T17:53:26.237 に答える
7

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.

于 2012-04-17T16:36:04.740 に答える
6

と を使用isEOFgetLineて入力を読み取ります。

これにより、 を使用して発生した遅延入出力の問題が回避されます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

于 2012-04-17T16:33:56.500 に答える