您的尝试有几处错误:
- 参数。你有
zipWith xs ys
,但是类型说第一个参数必须是一个函数,所以把它改成zipWith f xs ys
.
- 您正在递归调用 zipWith 。不过,ListPair.foldr 会为您处理这些,所以不要这样做。
- 您将 ListPair.foldr 0 作为其起始值。折叠函数总是采用与返回值相同类型的起始值- 我们希望 zipWith 返回一个列表,因此折叠函数应该将一个列表作为其起始值。空列表,即。
想想 ListPair.foldr 是如何工作的。我们可以一次做一个参数。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
此函数接受两个数字和一个列表,将两个数字相加,将它们放在列表的前面,然后返回它。类型是:
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
最后一个参数是一个包含两个列表的元组。我们放入一些随机列表,并在 sml 解释器中进行尝试:
- ListPair.foldr foo [] ([1,2,3],[10,20,30])
> val it = [11, 22, 33] : int list
现在,您需要做的就是用来自 zipWith 的参数替换 ListPair.foldr 的参数(foo 和两个随机列表),然后就完成了。