2

私は次の問題を抱えています:与えられた[String]String->IO Int。だから私は変換(マップ)を作成して取得することができます[IO Int]。今、私は2つのことをしなければなりません-開始から結果が肯定的であり、私が知る必要があるまでのアクションがすべてリスト処理されたというパフォーマンス。私は最初の非肯定的な結果の後に処理することを禁じられています。

takeWhileM2番目の質問に答えないで(長さの比較は実用的ではありません)、spanM禁止されていIOます。

もちろん、再帰関数は自分で書くこともできますが、Haskellの方法で、すべての高階関数を使って書きたいと思っています。

提案?おそらく、完全に別のアプローチを使用しますか?上記のタスクは、私のプロジェクトから少し単純化されたタスクです。

4

3 に答える 3

8

パッケージallMから使用できますmonad-loops

Prelude Control.Monad.Loops> let xs = ["a", "bb", "ccc", "dddd", "eeeee"]
Prelude Control.Monad.Loops> let f x = putStrLn x >> return (length x)
Prelude Control.Monad.Loops> let p x = x < 2
Prelude Control.Monad.Loops> allM (fmap p . f) xs
a
bb
False

allMinもありますがControl.Monad.ListM、適切に怠惰ではありません。肯定的な結果が得られた後も、計算を実行し続けます。

(ちなみに、私はあなたと一緒です。1回限りの再帰関数を書くのは嫌いです。)

于 2012-07-31T13:27:00.833 に答える
3

私は関数takeWhileMに精通しておらずspanM(そしてどちらもhoogleではありません)(編集:コメントに従って、それらはControl.Monad.ListMにあります)。

それを考えると、あなたにとって最善のことは、このタスクを実行するための1回限りの関数を作成することだと思います。後で同様のことを行うためにコードを書く必要があることが判明した場合は一般的な部分を除外して再利用できます。一般に、1回限りのコードを書くことには何の問題もありません。悪いのは、コードの重複です。

必要な関数を作成する方法はいくつかあります。考えられる方法の1つは、次のとおりです。

process :: [IO Int] -> IO Bool
process []     = return True
process [a]    = a >> return True
process (a:as) = do
    n <- a
    if n > 0
        then return False
        else process as
于 2012-07-31T11:47:00.497 に答える
0

takeWhileM@illusionoflife:@Chrisのソリューションで使用がどのように改善されるかわかりません。

例えば:

import Control.Monad.ListM

process :: [IO Int] -> IO Bool
process as = do
  taken <- takeWhileM (>>= return . (<= 0)) as
  return (length taken >= length as - 1)

(コードは検証されていません!)

@Chrisの見た目は、とりわけ、彼のソリューションでは、>=またはを使用する必要があるかどうかを判断する必要がないため、より読みやすくなってい==ます。その上、私が呼んでlengthいるので、無限の入力リストでそれを使用することはできません。

于 2012-07-31T12:27:15.067 に答える