0

ここに私のコードがあります:

boolTrueList :: [Bool] -> Bool
boolTrueList xs
  | length (filterFalse xs) > 0 = False
  | otherwise = True
  where
    filterFalse = filter (==False)

これは完全に機能していますが、同じことをfoldr/foldlで書き直したいのですが、行き詰まっています。

私の考えは、偽の値が見つかるまでリストを折りたたんでから停止することです。ヒントはありますか?

4

2 に答える 2

12

私の考えは、偽の値が見つかるまでリストを折りたたんでから停止することです。ヒントはありますか?

早く止めたい場合は、 を使用する必要がありますfoldrfoldl常にリスト全体をトラバースする必要があります (したがって、無限リストではまったく機能しません)。

あなたが望んでいるのは

foldr combine default list

これdefaultは空のリストの結果で、Trueここにあります。では、どのように組み合わせたらよいでしょうか。

aFalseに遭遇したらすぐに False を返したいので、

combine False _ = False

値が の場合、True続行する必要があるため、

combine True more = more

言い換えればcombine = (&&)、そう

boolTrueList = foldr (&&) True

または、さらに短い

boolTrueList = and
于 2012-12-06T13:42:20.397 に答える
5

私が非常に便利で直感的だと思った折り目について考える方法があります(私はおそらくこれをどこかで読んでいます)。これは最も効率的な解決策にはならないかもしれないことに注意してください、しかしここでの私の懸念は明確さです。

foldは、リストから値を作成する関数とは考えないでください。代わりに、リストの要素間に演算子を挿入する方法と考えてください。そうすると、foldはリストを式に変換する方法になります。したがって、たとえば、次のようになります。

foldr op I [A,..,Z]

次の拡張を生成します。

A op .. op Z op I 

あなたがその考えをあなたの問題に適用するならば、あなたがする必要があるのは何をすべきかを自問することです、そして私はあなたがA .. Zが真である場合にのみ真になることを確実にすることです?ヒントとして、私は通常、opに関する単位元です(0が加算のように、式を変更しない値)。

論理から、and(&&)は、そのすべてのオペランドが真である場合にのみ真であることがわかります。同様に、Trueは&&に関する単位元です。そうは言っても、拡張は次のようになります。

A && .. && Z && True

したがって、フォールドは次のようになります。

foldr (&&) True [A,..,Z]

つまり、関数は次のようになります。

boolTrueList x = foldr (&&) True x

または、よりポイントフリーのスタイルで:

boolTrueList = foldr (&&) True

反復を回避するために高階関数を使用するだけでは十分ではありません。反復的な考え方を回避する必要があります。「この時点で、この値は伝播する」ではなく、自由形式の表現で考えてください。多くの場合、反復は制限のない式を生成するための低レベルの方法であり、私たちの言語がこれを強制したため、式で考えることができる言語がある場合でも、私たちの考え方はしばしばそれに固執していますレベル。

于 2012-12-06T14:22:21.220 に答える