Haskell では、型は他のほとんどの言語よりも重要であり、有益です。Haskell を理解していない場合、最初のステップは型について考えることです。では、そうしましょう。ghci を起動して、次のように入力します。
Prelude> let mult_add d s = d + 10 * s
次に、そのタイプを尋ねます。
Prelude> :t mult_add
mult_add :: Num a => a -> a -> a
つまり、 mult_add はa
と 別のを取り、クラスのインスタンスである条件付きでa
を返します(これらを加算および乗算できるようにするため)。a
a
Num
この関数を書くために使用するよう求められているfoldr
ので、その型を見てみましょう:
Prelude> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
ちょっと難しそうなので、分解してみましょう。最初の部分は、2 つの変数 と の関数が必要であること(a -> b -> b)
を示しています。ええと、私たちはすでにそれらの 1 つを持っています - それはです。では、最初の引数としてフィードするとどうなるでしょうか?foldr
a
b
mult_add
mult_add
foldr
Prelude> :t foldr mult_add
foldr mult_add :: Num b => b -> [b] -> b
わかった!b
これで、 aと a [b]
( b
s のリスト) を受け取り、 a を返す関数ができましたb
。作成しようとしている関数は0
、空のリストが与えられたときに戻る必要があるため、残りの引数にいくつかの異なる値を指定して、空のリストを入力してみましょう:
Prelude> foldr mult_add 10 []
10
Prelude> foldr mult_add 5 []
5
ねえ、それは面白いです。数値x
と空のリストを渡すと、単に戻りますx
(注:これは に対して常に当てはまりますfoldr
。初期値x
と空のリストを指定すると、 の代わりにどの関数を使用しても、[]
が返されます。)x
mult_add
0
それでは、2 番目の引数としてそれを入力してみましょう。
Prelude> foldr mult_add 0 []
0
それはうまくいくようです。[1,2,3,4]
では、空のリストの代わりにリストをフィードするとどうなるでしょうか?
Prelude> foldr mult_add 0 [1,2,3,4]
4321
良い!それでうまくいくようです。問題は、なぜそれが機能するのかということです。理解するための秘訣foldr
は、関数を のすべての要素の間にfoldr f x xs
挿入し、さらに リストの最後に配置し、右からすべてを収集することです (これが右折りと呼ばれる理由です)。たとえば、次のようになります。f
xs
x
foldr f 0 [1,2,3] = 1 `f` (2 `f` (3 `f` 0))
ここで、バッククォートは、関数を中置形式で使用していることを示しています (したがって、最初の引数は左側のもので、2 番目の引数は右側のものです)。あなたの例ではf = mult_add
、2 番目の引数を 10 倍して最初の引数に追加します。
d `mult_add` s = d + 10 * s
だからあなたは持っています
foldr mult_add 0 [1,2,3] = 1 `mult_add` (2 `mult_add` (3 `mult_add 0))
= 1 `mult_add` (2 `mult_add` 3)
= 1 `mult_add` 32
= 321
これはあなたが期待することを行います。mult_add
これを確実に理解するには、逆に定義するとどうなるかを考えてみてください。
mult_add d s = 10 * d + s