了解类型的错误:"预期签名Int*Int->Int但有Int*Int->Int"
-
11-07-2019 - |
解决方案
我采取静态类型Yegge(和奥拉·比尼的)意见与一粒盐。如果你体会到什么静态类型给你,你将学习编程语言的类型系统是如何选择的作品。
IIRC,ML用来元组的 '*' 的语法。 <类型> * <类型>是具有两个元件的元组类型。所以,(1,2)将具有INT * INT类型。
两者Haskell和ML使用 - >为功能。在ML,INT * INT - > INT将是需要int和INT的元组并将其映射到一个int一个函数的类型
。一,你可能会看到一个隐约像一个从不同的语言来ML时,奥拉引述错误的原因是,如果你尝试过使用括号和逗号,参数类似于C或Pascal一会,到一个函数,它有两个参数。
麻烦的是,功能性语言多个参数的一般模型用作函数返回功能;所有的功能只需要一个参数。如果函数应该用两个参数,它,而不是接受一个参数,并返回一个参数,返回最终的结果,等等的功能。为了使所有这清晰,功能的应用程序是通过结合简单地完成(即放置表达式彼此旁边)。
所以,在ML简单的功能(注:我使用F#作为我ML)可能看起来有点像:
let f x y = x + y;;
它具有输入:
val f : int -> int -> int
(A函数取的整数,并且返回其本身需要的整数并返回一个整数的函数。)
但是,如果与天真地一个元组调用它:
f(1, 2)
...你会得到一个错误,因为你传递一个int * INT的东西期待一个int。
我希望这是“问题”奥拉试图在投诽谤。我不认为这个问题是那么糟糕,因为他认为,虽然;当然,在C ++模板是差远了。
其他提示
这是可能的,这是在参考了严重编写的编译器,其未能插入括号来消除歧义错误消息。具体来说,函数预期int
的元组和返回int
,但你通过int
的元组,并从int
一个功能int
。更具体地(在ML):
fun f g = g (1, 2);
f (42, fn x => x * 2)
这将产生类似于以下类型错误:
预期类型
int * int -> int
,得到类型int * (int -> int)
如果省略了括号,这种误差可以是烦人模棱两可。
值得注意的,这个问题是远离特定于辛德米尔纳。事实上,我不能认为任何怪异类型的错误其中是特定至H-M。至少,没有人像的例子给出。我怀疑奥拉只是吹烟
由于许多功能性的语言让你在,你可以重新绑定变量同样的方式重新绑定类型名称,它实际上是相当容易的,像这样的错误就结了,特别是如果你使用多少有些通用名称为您的类型(例如,t
)在不同的模块。下面是在OCaml的一个简单示例:
# let f x = x + 1;;
val f : int -> int = <fun>
# type int = Foo of string;;
type int = Foo of string
# f (Foo "hello");;
This expression has type int but is here used with type int
我在这里所做的是重新绑定类型标识符int
到一个新的类型,它是与内置int
类型不兼容。随着越来越多一点点的努力,我们可以得到更多或更少相同的错误上面:
# let f g x y = g(x,y) + x + y;;
val f : (int * int -> int) -> int -> int -> int = <fun>
# type int = Foo of int;;
type int = Foo of int
# let h (Foo a, Foo b) = (Foo a);;
val h : int * int -> int = <fun>
# f h;;
This expression has type int * int -> int but is here used with type
int * int -> int