0

次の質問が私に与えられました。

正の整数のリストを取り、リスト内の数値を逆順に使用して 10 進数を作成する関数 form_number_back を作成します。

たとえば、form_number_back [1, 2, 3, 4] は数値 4321 を返す必要があります。form_number_back [ ] は 0 を返します

これを行うには、以下の関数 folderr と mult_add を使用しますmult_add d s = d + 10*s

注: folderr と foldr1 は 2 つの異なる関数です。定義でfoldrの代わりにfoldr1を使用してみて、空のリストで同じ結果が得られるかどうかを確認してください。結果を説明してください。

で何も見つかりませんmult_add。多分それは関数名だと思ったが、彼女はform_number_back関数名として望んでいる. つまりmult_add、Haskell 関数です。

誰が私に何を説明できますmult_addか?それは正しく書かれていますか?mult_add自分のコードで使用することになっている別のユーザー作成関数はありますか?

編集 2

その型を取得するために関数の例を入れてみました..だから.. form_number_back [1, 2, 3, 4] :: Num b => b -> [b] -> b

私の関数は次のようになります

form_number_back a = foldr(mult_add)

しかし、型を返します

form_number_back :: Num b => [t] -> b -> [b] -> b

それを解消する方法を模索中[t]

4

1 に答える 1

4

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
于 2012-06-12T09:43:45.297 に答える