0

背景:SMLの初心者レベル

私の割り当てでは、ListPair.foldrを使用し、この関数のみを使用してzipWith関数を実装する必要があります。

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

ListPair.foldrは単一の'c要素を返し、zipWithは' cリストを返すので、当然、私のアプローチではListPair.foldrを繰り返し使用して、個々の'c要素をスピルアウトします。ListPair.foldrは、リストのペアを取得し、提供された関数に従ってそれらを互いに折りたたむため、目的の効果を得る唯一の方法は、一度に各リストから1つの要素を取得し、それをListPair.foldrにフィードすることです。リストのペアを取得し、結果を取得して、次のラウンドに連結します。また、関数を('a *'b->'c)から(' a *'b *'c->'c)に変換する必要があります。そのようです:

fun zipWith f [] l2 = []
| zipWith f l1 l2 = 
let val f2 = fn (a,b,c)=> f(a,b)+c   (* converting the function *)
    val xh = [hd(l1)]      (*first element of 'a list, as a list itself *)
    val yh = [hd(l2)]      (*first element of 'b list, as a list itself *)
    val xt = tl(l1)        (*taking the tail of 'a list*)
    val yt = tl(l2)        (*taking the tail of 'b list*)
in
    ListPair.foldr f2 0 (xh, yh)::    (*perform the operation with the two heads*)
    zipWith f xt yt                   (*recursively call zipWith with the remainder*)
end;

これは機能します。

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

しかし、ここで注意が必要なのは、これを再帰的に行うことは想定されていないことです。つまり、zipWith関数内でzipWithを呼び出すことはできません。これも可能ですか?私が読んだところによると、Haskellの実際のzipWith関数は再帰的に定義されています。これを非再帰的に行うにはどうすればよいですか?

教授がwhileループなどを使ってオブジェクト指向の方法でこれを行うように私たちに促しているとは想像できません(とにかく試しましたが、私のレベルはそれでも十分ではありません)。

私は完全に間違った方向にいますか?この質問にどのようにアプローチすればよいですか?

-----------------回答済み----------------

私は実際に最初にパッドのソリューションを試しました:

fun zipWith f l1 l2 = 
let val f2 = fn (a,b,c)=> f(a,b)::c
in
    ListPair.foldr f2 0 l1 l2
end;

しかし、[]ではなく0に追加していたため、機能しませんでした。タイプがうまくいかず、私はそれを理解できませんでした!

ありがとうございました!

4

1 に答える 1

4

あなたのアプローチは正しいですが、不必要に複雑です。関数は再帰的ですが、すでに再帰的な性質を持っているzipWithため、非再帰的に定義できます。ListPair.foldr

に近づくには、次の署名が付いzipWithた専用バージョンが必要ですListPair.foldr

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

これは、空のリストをアキュムレータとして渡し、途中でより大きなリストを作成することを意味します。に署名があるので、適応するのは非常に簡単ですzipWith f xs ysf'a * 'b -> 'c

fun zipWith f xs ys =
    ListPair.foldr (fn (a, b, cs) => f(a, b)::cs) [] (xs, ys)
于 2013-01-27T20:06:49.547 に答える