Использование ListPair.foldr для реализации zipWith в SML
Справочная информация: начальный уровень в 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», которые я затем помещаю в мой «c» список. ListPair.foldr берет пару списков и сворачивает их друг в друга в соответствии с предоставленной функцией, поэтому единственный способ получить желаемый эффект - это брать по одному элементу из каждого списка за раз, передавать его в 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. Это вообще возможно? Из того, что я прочитал, реальная функция zipWith в Haskell определяется рекурсивно; как мне сделать это нерекурсивно?
Я не могу себе представить, чтобы профессор призывал нас делать это объектно-ориентированным образом с помощью циклов 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 вместо []. Типы не сработали, и я не мог понять это!
Спасибо!