3
getText = do
    c <- getChar
    s <- getText
    return (c : s)

main = do
    s <- getText
    putStr s

私が期待しているのは、「Enter」を押すたびに入力行がエコーされることです。しかし、何もエコーされません... (これが無限ループであることはわかっています)return上記のすべての "IO" が実行されるまで、それは行われないようです。...

ただし、次のコード:

main = do
    s <- getContents
    putStr s

入力直後の行を表示します。

関数 が与えられた場合、次のように動作するgetChara を記述できますか?getTextgetContents

4

3 に答える 3

8

これは...の仕事ですunsafeInterleaveIO-怠惰なIOを可能にする特別なアクション。これにより、IOアクションをサンクにバインドされたアクションに変えることができます。その後、これを構造体に格納できます。アクションは、結果が要求された場合にのみ評価されます。

getText = unsafeInterleaveIO $ do
    c <- getChar
    s <- getText
    return (c : s)

getTextこれで、各getCharの計算を一時停止するだけで、すぐに戻ります。結果が必要な場合は、実行されます。

于 2013-02-16T15:52:30.543 に答える
7

unsafeInterleaveIOこれは、からの関数を 使用して実行できますSystem.IO.Unsafe。その後、あなたのgetText関数は次のようになります

getText = do
    c <- getChar
    s <- unsafeInterleaveIO $ getText
    return (c : s)

少し抽象化すると、この動作を一般化する関数を取得できます

lazyDoIO :: IO a -> IO [a]
lazyDoIO act = unsafeInterleaveIO $ do
    now <- act
    rest <- lazyDoIO act
    return (now : rest)

getText = lazyDoIO getChar

ただし、ほとんどのハスケラーはこれを行うことに固執します。生成されたデータのインクリメンタルストリーム処理を実行する場合は、またはIOのようなライブラリを使用する方がはるかに安全です。PipesConduits

于 2013-02-16T15:51:56.077 に答える
1

Enterについて話しますが、コードでチェックしません。

これを試して:

getText = do
    c <- getChar
    if (c == '\n')
       then return [c]
       else do
              s <- getText
              return (c : s)

main = do
    s <- getText
    putStr s
于 2013-02-16T16:03:13.857 に答える