Jef*_*eff 1 f# type-inference static-typing typechecking hindley-milner
我想了解有关类型推断的规则,因为我希望将其纳入自己的语言中,并且本着这种精神,我一直在研究F#的类型推断,以下让我感到奇怪。
这将进行编译,并且id
为'a -> 'a
,(如果我没有记错的话)表示每个调用都使用“新鲜”类型。
let id x = x
let id1 = id 1
let id2 = id "two"
Run Code Online (Sandbox Code Playgroud)
但是,当使用运算符时,似乎是第一次调用确定了该函数的签名。
在这里,mul
据报道是int -> int -> int
let mul x y = x * y
let mul1 = mul 1 2
let mul2 = mul 1.1 2.2 // fails here
Run Code Online (Sandbox Code Playgroud)
如果我重新排序,mul
则为float -> float -> float
:
let mul x y = x * y
let mul2 = mul 1.1 2.2
let mul1 = mul 1 2 // fails here
Run Code Online (Sandbox Code Playgroud)
您能从类型检查实现的角度解释(最好是非学术性的)术语是什么规则,以及规则如何工作?它是否遍历函数以在每次引用时检查其类型?还是有其他方法?
First note that this will not happen if we declare mul
as an inline function:
let inline mul x y = x * y
let mul1 = mul 1 2 // works
let mul2 = mul 1.1 2.2 // also works
Run Code Online (Sandbox Code Playgroud)
Here the inferred type of mul
will be as follows:
x: ^a -> y: ^b -> ^c
when ( ^a or ^b) : (static member ( * ) : ^a * ^b -> ^c)
Run Code Online (Sandbox Code Playgroud)
This type means that the parameters x
and y
can have any type (doesn't even have to be the same type) as long as at least one of them has a static member named *
that takes arguments of the same types as x
and y
. The return type of mul
will be the same as that of the *
member.
So why don't you get the same behavior when mul
isn't inline? Because member constraints (i.e. type constraints that say that a type must have specific members) are only allowed on inline functions - that's also why the type variables have a ^
in front instead of the usual '
: to signify that we're dealing with a different, less limited kind of type variable.
那么为什么存在对非内联函数的限制呢?由于.NET支持。类型约束(例如“ T实现接口I”)可以在.NET字节码中表示,因此可以在所有函数中使用。类型约束(例如“ T必须具有名为U的特定成员,且类型为X的X”)无法表达,因此在普通函数中是不允许的。由于内联函数在生成的.NET字节码中没有相应的方法,因此不需要在.NET字节码中表示它们的类型,因此限制并不适用于它们。
归档时间: |
|
查看次数: |
82 次 |
最近记录: |