Использование 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 вместо []. Типы не сработали, и я не мог понять это!

Спасибо!

Ответы на вопрос(1)

Ваш ответ на вопрос