質問

私は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) その関数の議論です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top