-1

几天前我问过这个问题,但现在我对这个问题有了更多的了解。但是我仍然遇到操作员和操作数不同意的问题:

使用 ListPair.foldr 我需要创建一个函数 zipWith 组合成对的两个列表。整体函数的类型应该是:

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

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

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

我的尝试:

fun zipWith xs ys = ListPair.foldr(zipWith(x,y,z) => (x+y)::z) 0 xs ys
4

1 回答 1

4

您的尝试有几处错误:

  1. 参数。你有zipWith xs ys,但是类型说第一个参数必须是一个函数,所以把它改成zipWith f xs ys.
  2. 您正在递归调用 zipWith 。不过,ListPair.foldr 会为您处理这些,所以不要这样做。
  3. 您将 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 和两个随机列表),然后就完成了。

于 2013-01-29T18:33:38.873 回答