(* val bar = fn : (’a * ’b -> ’b) -> ’b -> ’a list -> ’b *)
fun bar f b nil = b
| bar f b (h::t) = f (h, bar f b t)
这个功能是给我们的,说明了解它的功能。给出的唯一进一步信息是参数是二元函数,值和列表。通过查看,我已经知道如果列表为nil,则返回b值,否则它将二进制函数应用于列表头并进行递归。我只是不明白如何解释这一行:
(* val bar = fn : (’a * ’b -> ’b) -> ’b -> ’a list -> ’b *)
有许多教程解释SML的输入,但我找不到足够深入的东西来应用于此。任何人都可以把它翻译成英文,所以我知道它的工作原理以供将来参考吗?
答案 0 :(得分:3)
要了解此类型的sgnature,您需要先了解currying。
像
这样的定义fun sum a b = a + b
的类型为int -> int -> int
。
它是一个变量(整数)的函数,其中返回值本身就是一个函数,它将整数发送给整数。
例如,val f = sum 1
向f
分配一个函数,该函数在其输入中添加一个函数(换句话说,后继函数),以便例如f 5
求值为6。 / p>
在实践中,这些功能通常像sum 3 4
一样使用,但在那里发生的事情并非将2个值传递给sum
。而是传递一个值3,它返回一个函数,然后将此返回值应用于4.因此,sum 3 4
应该被解析为(sum 3) 4
而不是sum (3,4)
- 将是一个类型错误。
请注意,这与
等根本不同fun add (a,b) = a + b
其中是两个变量的函数,它具有类型int * int -> int
,它与总和的int -> int -> int
类型不同。后者不是前者的语法糖,而是具有根本不同的语义。
在阅读诸如int -> int -> int
之类的内容时,您应将其视为右关联。换句话说,它与int -> (int -> int)
相同。
('a * 'b -> 'b) -> 'b -> 'a list -> 'b
发生的另一件事是使用类型变量 'a, 'b
。这意味着您尝试解析的类型是高阶多态函数。它'a
和'b
可以代表任何类型。
将所有这些放在一起,类型f
的函数('a * 'b -> 'b) -> 'b -> 'a list -> 'b
是一个函数,它将任何类型为'a * 'b -> 'b
形式的函数作为输入(两个变量的函数)其返回类型是第二个变量的类型)。 f
的返回值是'b -> 'a list -> 'b
形式的函数。后者是一个函数,它接受'b
类型的元素并返回一个函数,该函数将'a lists
发送到'b
类型的对象
您可以通过说f
是 curried 函数来概括它,该函数采用类型为('a * 'b -> 'b)
的函数,类型为'b
的值,列表类型为'a
的值,并返回类型'b
的值。这是足够准确的,但不要认为它等同于类型
('a * 'b -> 'b) * 'b * 'a list -> 'b
顺便说一下,SML中最有用的两个函数foldl
和foldr
都有('a * 'b -> 'b) -> 'b -> 'a list -> 'b
类型,所以这不仅仅是一个学术练习。能够打开这种类型的描述是能够正确使用这些功能的关键。
答案 1 :(得分:1)
我能够根据所谓的类型推理找到解决方案。我之前从未学过这个,但是
(* val bar = fn : (’a * ’b -> ’b) -> ’b -> ’a list -> ’b *)
显示函数的参数和返回类型。
(’a * ’b -> ’b)
指的是第一个参数函数。它本身需要2个参数('b
和'a
)并返回1个值'b
。
'b
引用第二个参数,即值。
'a list
是指值列表,是函数中的第三个参数。
最后,最后一个'b
是返回值。