2009-07-15 11 views
12

私はHaskellから呼び出すC言語で書かれた関数をいくつか持っています。これらの関数はIO (CInt)を返します。時には、それらの関数が何を返すかにかかわらず、すべての関数を実行したい場合がありますが、これは簡単です。サンプルコードのために、これは現在何が起こっているかの一般的な考え方です:ハスケル:モナドのテイク?

Prelude> let f x = print x >> return x 
Prelude> mapM_ f [0..5] 
0 
1 
2 
3 
4 
5 
Prelude> 

私は私の希望副作用を取得し、私は結果を気にしないでください。しかし、今私は望む結果を返さない最初の項目の直後に実行を停止する必要があります。 - 4以上の戻り値が停止し、実行を要求するのは、言ってみましょう、私はやってをしたい何することはこれです:

 
<interactive>:1:22: 
    Couldn't match expected type `[b]' against inferred type `IO a' 
    In the first argument of `mapM', namely `f' 
    In the second argument of `($)', namely `mapM f ([0 .. 5])' 
    In the expression: takeWhile (< 4) $ mapM f ([0 .. 5])

そして、それは理にかなって:私は、このエラーが発生します

Prelude> takeWhile (<4) $ mapM f [0..5] 

私の結果はまだIOモナドに含まれており、IOモナドに含まれる2つの値を比較することはできません。私はこれが正確にモナドの目的であることを知っています - 結果を連鎖させ、ある条件が満たされたときに処理を破棄しますが、この場合IOモナドを「包む」方法があります私の選択の、MonadPlusのインスタンスを記述することなく?

takeWhileの目的のために、fの値をちょうど "解除"できますか?

これはファンクタが適合するソリューションですか? Functorはまだ私と「クリック」していませんが、これを使うのは良い状況かもしれないという印象を持っています。


更新:

@sthは、私が欲しいものに近い答えを持っている - 実際には、それは私がのために何が起こっていたか、ほぼ正確だが、私はまだがあるかどうかを見てみたいと思います標準明示的に再帰的でないソリューション - これは結局ハスケルです!私がどのように私の質問に言い聞かせたかを振り返ってみると、今私は自分が望む行動について十分にはっきりしていないことがわかります。

上記で例として使用した機能は単なる例です。実際の関数はC言語で書かれ、副作用のためにのみ使用されます。私はmapM_ f (takeWhile (<4) [0..5])の@ Tomの提案を使用することはできません。なぜなら、入力が実際に実行されるまで成功するか失敗するかわからないからです。

私は本当に返されたリストを気にしません。リストが使い果たされるか最初のC関数が失敗コードを返すまで、C関数を呼び出すだけです。

Cスタイルの擬似コードでは、私の行動は次のようになります(?必要があります)

do { 
    result = function_with_side_effects(input_list[index++]); 
} while (result == success && index < max_index); 

だからもう一度、@のSTHの答えは、結果が破棄されることを除いて、私が欲しいの正確な動作を行います。 dropWhileM_機能は私の目的と同等です。なぜ、そのような機能がないのですか?またはtakeWhileM_がControl.Monadにありますか? a similar discussion on a mailing listがあることがわかりますが、それは何も起こっていないようです。

+0

'sortBy'は' sortByM :: Monad m =>(a - > a - > m Ordering) - > [a] - > m [a] 'で定義されていないことは残念です。 –

答えて

関連する問題