プレリュードから:
foldl1:リストの最初の2つの項目を取得し、それらに関数を適用してから、この結果と3番目の引数を関数にフィードします。
なぜこのようなものを書くことができないのですか?
foldl1 (==) [6, 6, 6]
foldl1 (\x y -> x == y) [6, 6, 6]
プレリュードから:
foldl1:リストの最初の2つの項目を取得し、それらに関数を適用してから、この結果と3番目の引数を関数にフィードします。
なぜこのようなものを書くことができないのですか?
foldl1 (==) [6, 6, 6]
foldl1 (\x y -> x == y) [6, 6, 6]
リストのすべての要素が等しいかどうかを確認したい場合、簡単な解決策は次のとおりです。
allEqual [] = True --(edit: this case is not necessary as pointed out by sepp2k)
allEqual xs = all (== head xs) xs
誰かがこれを行うためのよりエレガントな方法を書くでしょう、私は確信しています、しかしこれは実用的です。
編集:提案をしてくれたsepp2kに感謝します。
編集:アンタルは私の推論が間違っていたと指摘します。これが本当の理由を与えるコメントの関連部分です(私はこれを逐語的に取るのは気分が悪いですが、この答えは受け入れられたので削除できません):
これが機能しない理由は、のタイプはfoldl1
です(a -> a -> a) -> [a] -> a
が、のタイプは(==)
ですNum a => a -> a -> Bool
。Bool
はではないため、Num
タイプ(==)
が一致しないa -> a -> a
ため、の適用foldl1
は拒否されます。それが受け入れられた場合、あなたはあなたがやろうとしていた状況になってしまうでしょうTrue == 6
、しかし型システムはあなたがそもそもそこまで到達することは決してありません。
元の答え(後の推論は正しくありません):
==
2Int
秒かかり、を返しますBool
。最初の反復の後、サンプルリストはになり[True, 6]
ます。True
次に、どちらが失敗したかを比較しようとし6
ます。
別のバージョンは次のとおりです。
allEqual xs = and $ zipWith (==) xs (tail xs)
フォールドを使用する場合は、次の変更をお勧めします。
allEqual xs = foldr (\x acc -> x == head xs && acc) True xs
all
これは、すでに提案されているアプローチと非常によく似ています。これとall
アプローチの両方が無限のリストで機能することに注意してください(答えがである限りFalse
)。
非常に長い有限リストの場合、非常にまれなケースですが、厳密な左折りからパフォーマンスが向上する場合があります。
allEqual xs = foldl' (\acc x -> acc && x == head xs) True xs
ただし、(この実装では)に等しい数の折り畳みステップしか実行しないため、この問題には一般的に正しい折り畳みの方が適していますlength $ takeWhile (== head xs) xs
。左の折り目はlength xs
毎回折り畳みステップを実行します。