背景: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に追加していたため、機能しませんでした。タイプがうまくいかず、私はそれを理解できませんでした!
ありがとうございました!