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を返します(これらを加算および乗算できるようにするため)。aaNum
この関数を書くために使用するよう求められているfoldrので、その型を見てみましょう:
Prelude> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
ちょっと難しそうなので、分解してみましょう。最初の部分は、2 つの変数 と の関数が必要であること(a -> b -> b)を示しています。ええと、私たちはすでにそれらの 1 つを持っています - それはです。では、最初の引数としてフィードするとどうなるでしょうか?foldrabmult_addmult_addfoldr
Prelude> :t foldr mult_add
foldr mult_add :: Num b => b -> [b] -> b
わかった!bこれで、 aと a [b]( bs のリスト) を受け取り、 a を返す関数ができましたb。作成しようとしている関数は0、空のリストが与えられたときに戻る必要があるため、残りの引数にいくつかの異なる値を指定して、空のリストを入力してみましょう:
Prelude> foldr mult_add 10 []
10
Prelude> foldr mult_add 5 []
5
ねえ、それは面白いです。数値xと空のリストを渡すと、単に戻りますx(注:これは に対して常に当てはまりますfoldr。初期値xと空のリストを指定すると、 の代わりにどの関数を使用しても、[]が返されます。)xmult_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挿入し、さらに リストの最後に配置し、右からすべてを収集することです (これが右折りと呼ばれる理由です)。たとえば、次のようになります。fxsx
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