【问题标题】:SML currying ( functional prog)?SML 柯里化(功能编)?
【发布时间】:2013-01-13 08:29:08
【问题描述】:

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

使用 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

【问题讨论】:

标签: functional-programming sml currying fold


【解决方案1】:

您的尝试有几处错误:

  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

现在,您只需将 ListPair.foldr 的参数(foo 和两个随机列表)替换为 zipWith 中的参数,就完成了。

【讨论】:

  • 非常感谢您的解释。我想通了。
猜你喜欢
  • 1970-01-01
  • 2013-11-07
  • 2013-10-04
  • 1970-01-01
  • 1970-01-01
  • 2015-05-13
  • 2017-06-09
  • 2022-11-22
  • 2019-05-21
相关资源
最近更新 更多