さて、カリー化された関数 の型シグネチャを見てみましょうfoldr
:
>:t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
したがってfoldr
、バイナリ関数 (つまりa->b->b
)、b
値、値のリストを取り、a
値を返しb
ます。
より明確な定義を得るために、 のドキュメントも見てみましょう。foldr
二項演算子、開始値 (通常は演算子の右側の同一性)、およびリストに適用される foldr は、二項演算子を使用してリストを右から左に縮小します。
では、型シグネチャを見てみましょうmyConcat xs = foldr (++) []
> :t myConcat
myConcat :: t -> [[a]] -> [a]
うーん...それは私たちが望んでいたものではありません...
問題はfoldr
、 type の値を提供したことがないことです[a]
。したがって、次myConcat
のように、満たすために任意のタイプの値xs
と[a]
complete するタイプの値が必要foldr (++) []
です。
> myConcat 2 [[1,2],[3,4]]
[1,2,3,4]
> myConcat Nothing [[1,2],[3,4]]
[1,2,3,4]
それは機能しますが、最初の引数は無駄です。
ただし、そのxs
値を に渡すとfoldr (++) []
、次のようになります。
myConcat xs = foldr (++) [] xs
その型シグネチャを確認します
> :t myConcat
myConcat :: [[a]] -> [a]
ああ、ずっといい。myConcat を使用xs
して関数を完成させfoldr
ます。
また、myConcat = foldr (++) []
も機能し、実際にはポイントフリー スタイル プログラミングの例です。の型シグネチャを確認するとfoldr (++) []
、
> :t foldr (++) []
foldr (++) [] :: [[a]] -> [a]
部分適用foldr
によって最初の 2 つの引数を既に提供しているので、値を取り、必要な処理を行う関数が返されます。したがって、名前に割り当てるだけで、上記の例と同じように機能しますが、引数を明示的に渡す必要はありません![[a]]
> let myConcat = foldr (++) []
> :t myConcat
myConcat :: [[a]] -> [a]
> myConcat [[1,2],[3,4]]
[1,2,3,4]