我如何解释这个 SML 类型表达式?
How do I interpret this SML typing expression?
(* 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,则它 returns b 值,否则它将二进制函数应用于列表头并递归。我只是不明白如何解释这一行:
(* val bar = fn : (’a * ’b -> ’b) -> ’b -> ’a list -> ’b *)
有许多教程解释了 SML 的类型,但我找不到任何足够深入的教程来应用它。谁能把它翻译成英文,以便我知道它是如何工作的以供将来参考?
我能够根据所谓的类型推断找到解决方案。我以前从未学过这个,但是
(* val bar = fn : (’a * ’b -> ’b) -> ’b -> ’a list -> ’b *)
是函数的参数和 return 类型的显示。
(’a * ’b -> ’b)
指的是第一个参数函数。它本身需要 2 个参数('b
和 'a
)和 returns 1 个值 'b
.
'b
指的是第二个参数,一个值。
'a list
指的是值列表,函数中的第三个参数。
最后,最后的'b
就是return的值。
要理解这个类型签名,你需要先理解currying。
定义如
fun sum a b = a + b
类型为 int -> int -> int
.
它是一个变量(一个整数)的函数,其中return值本身就是一个函数,一个将整数发送到整数的函数。
例如,val f = sum 1
将向其输入加一的函数(换句话说,后继函数)分配给 f
,因此,例如,f 5
的计算结果为 6 .
在实践中,这样的函数经常像 sum 3 4
那样使用,但是那里发生的事情 不是 将 2 个值传递给 sum
。相反,传递了一个值 3,return 是一个函数,然后将这个 returned 值应用于 4。因此,sum 3 4
应该被解析为 (sum 3) 4
而不是比 sum (3,4)
-- 这将是一个类型错误。
请注意,这与
fun add (a,b) = a + b
其中是两个变量的函数,它的类型是int * int -> int
,与sum的int -> int -> int
类型不同。后者不是前者的语法糖,而是具有根本不同的语义。
当阅读诸如 int -> int -> int
之类的内容时,您应该将其阅读为右结合。换句话说,它与 int -> (int -> int)
.
相同
('a * 'b -> 'b) -> 'b -> 'a list -> 'b
发生的另一件事是使用 类型变量 'a, 'b
。这意味着您要解析的类型是高阶 polymorphic 函数。它'a
和'b
可以表示任何类型。
将它们放在一起,('a * 'b -> 'b) -> 'b -> 'a list -> 'b
类型的函数 f
是一个将类型为 'a * 'b -> 'b
形式的任何函数作为输入的函数(函数return 类型为第二个变量类型的两个变量)。 f
的 return 值是 'b -> 'a list -> 'b
形式的函数。后者是一个接受 'b
类型元素的函数,return 是一个将 'a lists
发送到 'b
类型对象的函数
你可以这样总结它 f
是一个 curried 函数,它接受一个 ('a * 'b -> 'b)
类型的函数,一个 [=29] 类型的值=],'a
类型的值列表,return 是 'b
类型的值。这足够准确,但不要误以为它等同于类型
的函数
('a * 'b -> 'b) * 'b * 'a list -> 'b
顺便说一下,SML 中两个最有用的函数 foldl
和 foldr
的类型为 ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
,因此这不仅仅是一个学术练习。能够解包这样的类型描述是能够正确使用这些函数的关键。
(* 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,则它 returns b 值,否则它将二进制函数应用于列表头并递归。我只是不明白如何解释这一行:
(* val bar = fn : (’a * ’b -> ’b) -> ’b -> ’a list -> ’b *)
有许多教程解释了 SML 的类型,但我找不到任何足够深入的教程来应用它。谁能把它翻译成英文,以便我知道它是如何工作的以供将来参考?
我能够根据所谓的类型推断找到解决方案。我以前从未学过这个,但是
(* val bar = fn : (’a * ’b -> ’b) -> ’b -> ’a list -> ’b *)
是函数的参数和 return 类型的显示。
(’a * ’b -> ’b)
指的是第一个参数函数。它本身需要 2 个参数('b
和 'a
)和 returns 1 个值 'b
.
'b
指的是第二个参数,一个值。
'a list
指的是值列表,函数中的第三个参数。
最后,最后的'b
就是return的值。
要理解这个类型签名,你需要先理解currying。
定义如
fun sum a b = a + b
类型为 int -> int -> int
.
它是一个变量(一个整数)的函数,其中return值本身就是一个函数,一个将整数发送到整数的函数。
例如,val f = sum 1
将向其输入加一的函数(换句话说,后继函数)分配给 f
,因此,例如,f 5
的计算结果为 6 .
在实践中,这样的函数经常像 sum 3 4
那样使用,但是那里发生的事情 不是 将 2 个值传递给 sum
。相反,传递了一个值 3,return 是一个函数,然后将这个 returned 值应用于 4。因此,sum 3 4
应该被解析为 (sum 3) 4
而不是比 sum (3,4)
-- 这将是一个类型错误。
请注意,这与
fun add (a,b) = a + b
其中是两个变量的函数,它的类型是int * int -> int
,与sum的int -> int -> int
类型不同。后者不是前者的语法糖,而是具有根本不同的语义。
当阅读诸如 int -> int -> int
之类的内容时,您应该将其阅读为右结合。换句话说,它与 int -> (int -> int)
.
('a * 'b -> 'b) -> 'b -> 'a list -> 'b
发生的另一件事是使用 类型变量 'a, 'b
。这意味着您要解析的类型是高阶 polymorphic 函数。它'a
和'b
可以表示任何类型。
将它们放在一起,('a * 'b -> 'b) -> 'b -> 'a list -> 'b
类型的函数 f
是一个将类型为 'a * 'b -> 'b
形式的任何函数作为输入的函数(函数return 类型为第二个变量类型的两个变量)。 f
的 return 值是 'b -> 'a list -> 'b
形式的函数。后者是一个接受 'b
类型元素的函数,return 是一个将 'a lists
发送到 'b
你可以这样总结它 f
是一个 curried 函数,它接受一个 ('a * 'b -> 'b)
类型的函数,一个 [=29] 类型的值=],'a
类型的值列表,return 是 'b
类型的值。这足够准确,但不要误以为它等同于类型
('a * 'b -> 'b) * 'b * 'a list -> 'b
顺便说一下,SML 中两个最有用的函数 foldl
和 foldr
的类型为 ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
,因此这不仅仅是一个学术练习。能够解包这样的类型描述是能够正确使用这些函数的关键。