2016-09-02 14 views
0

私の主な目標は、stderrをファイルにリダイレクトすることです。Haskell - 任意の関数と引数リストを別の関数の引数として渡す

私は、私は、これは、より一般的にし、catchOutputに任意の関数と引数リストを渡し、関数の結果としてだけでなく、stderrに書き込まれたメッセージを取得することを望んだ...

catchOutput :: IO a -> IO (res, String) 
catchOutput f = do 
    tmpd <- getTemporaryDirectory 
    (tmpf, tmph) <- openTempFile tmpd "haskell_stderr" 
    stderr_dup <- hDuplicate stderr 
    hDuplicateTo tmph stderr 
    hClose tmph 
    res <- f 
    hDuplicateTo stderr_dup stderr 
    str <- readFile tmpf 
    removeFile tmpf 
    return (res, str) 

を次のコードスニペットのホールドを得ました(もしあれば)。

は、I型の引数リストは、[Data.Dynamic]うまくいくかもしれないと思ったが、私はこれも可能です

res <- Data.List.foldl (f . fromDyn) Nothing $ args 

を持つ関数の結果を取得できませんでしたか?ヘルプは非常に高く評価されます。

+2

他の言語では、関数と引数のリストを渡す必要があります。彼らは厳密であるか、副作用を乗り越えている。ハスケルでは、それを行う必要はありません。関数が純粋であれば、その結果(とにかく評価されません)を 'a'として渡します。さもなければ上でやっているように 'IO a'アクションを渡します(後で実行されるまでは実行されません)。 – chi

+0

関数とその引数を渡すのではなく、関数の結果を 'catchOutput'に渡すのはなぜですか? –

答えて

3

Data.Dynamicを使用する理由はありません。にstderrをリダイレクトすることによって

  1. :あなたはすでに、それはあなたがちょうどそれを使用することができますaだ、しかしすなわち

    catchOutput :: IO a -> IO (a, String) 
    

    注意、あなたのアプローチであり、いくつかの重要な問題のことをfの戻り値の型を入力知っていますこれは他のすべての並行スレッドにも影響します。したがって、関係のないデータを一時ファイルに送信する可能性があります。

  2. stderrがリダイレクトされている間に例外がスローされた場合、元のstderrは復元されません。 2つのhDuplicateTo行(この場合はhClosef)間の操作は例外をスローする可能性があり、スレッドが非同期例外を受け取ることがあります。このため、コードの例外を安全にするには、bracketのようなものを使用する必要があります。
+0

私が理解しているように、エレメントが異なるタイプのリストを生成することはできません。したがって、引数リストのさまざまな要素にData.Dynamicを使用します。 –

+0

はい、さまざまなタイプの要素を持つリストは作成できませんが、コードにリストは表示されません。 – redneb

関連する問題