Haskellのfoldr関数を取得する引数はいくつありますか?
質問
私はHaskellが初めてで、本を読んでいます 「現実世界のハスケル」. 。本の第4章では、著者は、foldを使用してグループビー機能を書き直すための演習として尋ねます。本の読者の一人(Octavian Voicu)は次の解決策を与えました。
theCoolGroupBy :: (a -> a -> Bool) -> [a] -> [[a]]
theCoolGroupBy eq xs = tail $ foldr step (\_ -> [[]]) xs $ (\_ -> False)
where step x acc = \p -> if p x then rest p else []:rest (eq x)
where rest q = let y:ys = acc q in (x:y):ys
私の質問は簡単です: Foldrは、関数、初期値、リストという3つの引数を必要とします。ただし、コードの2行目では、foldrが4つの引数を取ります。 なぜこれが起こるのですか?ありがとうございました。
解決
スコットの答えは正しい、 foldr
関数なので、これが foldr
4つの引数を取ります。 foldr
関数は3つの引数(関数、ベース、リスト)を取得します。
*Main> :type foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
ここでは、それほど複雑ではない例を挙げてください。
inc :: Int -> (Int -> Int)
inc v = \x -> x + v
test = inc 2 40 -- output of test is 42
上記のコードでは、 inc
1つの議論を取ります、 v
, 、およびその議論を増やす関数を返します v
.
以下に示すように、戻りタイプのタイプ inc 2
関数なので、その引数は最後に単に追加できます。
*Main> :type inc
inc :: Int -> Int -> Int
*Main> :type inc 2
inc 2 :: Int -> Int
*Main> :type inc 2 40
inc 2 40 :: Int
括弧を使用して、戻り値が関数であることを強調することができますが、機能的には上記のコードと同一です。
*Main> (inc 2) 40
42
PS:私は元のコメントの著者です:)
他のヒント
この状況では、のタイプの署名を見るのが最善だと思います foldr
:
foldr :: (a -> b -> b) -> b -> [a] -> b
そして、それを私たちが持っている表現と一致させるために(明確にするために括弧を付けて追加):
(foldr step (\_ -> [[]]) xs) (\_ -> False)
の2番目の議論 foldr
結果と同じタイプです。この場合、2番目の引数は関数です。この場合、これは次のことを意味します foldr
3つの引数を持つ式が関数になります。
FoldR関数の4番目の議論であると思うものは、FoldR結果の最初の議論とも考えられます。
Haskellのすべての関数は、1つの引数を1つだけ取ります。タイプの関数があるとき a -> b -> c
, 、それはただ書くための短い方法です a -> (b -> c)
, 、つまり、1つの引数を取り、別の引数を取る関数を生成する関数。見る カリー 詳細については。
この場合、 @sepp2kの回答を参照してください。 foldr
関数を生成すると、別の(「4番目」)引数が必要です。
この場合 foldr
関数を構築するために使用されます。 (\_ -> False)
その関数の議論です。