-1

数日前にこの質問をしましたが、今ではこの件についてより理解が深まりました。しかし、演算子とオペランドが一致しないという問題がまだあります。

ListPair.foldr を使用して、ペアごとに 2 つのリストを結合する関数 zipWith を作成する必要があります。関数全体の型は次のようになります。

zipWith : ('a * 'b -> 'c) -> 'a list -> 'b list -> 'c list

ListPair.foldr : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c

- zipWith (fn (x, y) => x + y) [1,2,3,4] [10,20,30,40];
  val it = [11,22,33,44] : int list

私の試み:

fun zipWith xs ys = ListPair.foldr(zipWith(x,y,z) => (x+y)::z) 0 xs ys
4

1 に答える 1

4

あなたの試みにはいくつかの間違いがあります:

  1. パラメータ。がありますzipWith xs ysが、タイプは最初のパラメーターが関数でなければならないことを示しているので、それを に変更しzipWith f xs ysます。
  2. zipWith を再帰的に呼び出しています。ただし、ListPair.foldr がそれを処理してくれるので、そうしないでください。
  3. ListPair.foldr 0 を開始値として指定しています。折り畳み関数は常に戻り値と同じ型の開始値を取ります- zipWith がリストを返すようにしたいので、折り畳み関数は開始値としてリストを取る必要があります。つまり、空のリストです。

ListPair.foldr がどのように機能するかを考えてみてください。一度に 1 つのパラメーターを実行できます。ListPair.foldr のタイプは次のとおりです。

fn : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c

最初のパラメーターは次のタイプの関数です。

fn : 'a * 'b * 'c -> 'c

例としておもちゃの関数を作ってみましょう:

fun foo (a, b, acc) = a+b :: acc

この関数は、2 つの数値とリストを受け取り、2 つの数値を加算してリストの前に配置し、それを返します。タイプは次のとおりです。

fn : int * int * int list -> int list

これは、ListPair.foldr の最初のパラメーターの型シグネチャにうまく対応しています。

では、型を見てみましょうListPair.foldr foo

fn : int list -> int list * int list -> int list

次のパラメータは int リストで、折り畳みの開始値です。これが空のリストであることはすでにわかっています。のタイプListPair.foldr foo []は次のとおりです。

fn : int list * int list -> int list

最後のパラメーターは、2 つのリストを含むタプルです。ランダムなリストをいくつか入れて、sml インタープリターで試してみます。

- ListPair.foldr foo [] ([1,2,3],[10,20,30])
> val it = [11, 22, 33] : int list

あとは、ListPair.foldr のパラメーター (foo と 2 つのランダム リスト) を zipWith のパラメーターに置き換えるだけで完了です。

于 2013-01-29T18:33:38.873 に答える