为什么算术运算符的参数类型默认为int?

时间:2014-11-28 10:18:26

标签: f#

我是F#的新手,我很惊讶地发现f x y = x + y的类型实际上是int -> int -> intAppearently,这是由于一些表现权衡。

为什么这实际上是必要的?为什么不将类型推断为'a -> 'a -> 'a或类似的东西?它似乎可以进行比较:g x y = x < y的类型是x:'a -> y:'a -> bool when 'a : comparison。为什么不对算术运算符呢?

编译器无法从调用站点静态推断出特定的基本类型,并从那里专门化泛型函数,如果失败则回退到某些动态调度?

这可能很明显,但我找不到任何好的资源。这种行为背后的原因是什么?

1 个答案:

答案 0 :(得分:10)

是的,对于那些运算符int是推断的默认类型,除非您指定另一个或由使用推断。如果要为所有类型定义它们,则必须使函数内联:

let inline f x y = x + y

但请注意签名是:

x: ^a -> y: ^b ->  ^c
    when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^c)

这是因为在.NET中你不能使用member constraints但是F#在编译时解析它们。这就是为什么你会看到那些'帽子类型'以及那些类型应该定义静态成员(+)的约束。

另外请注意,类型变量不是你建议的a -> a -> a,因为在.NET框架中并非所有的加法操作都遵循该签名。在像Haskell这样的其他环境中,情况有所不同,在那里添加严格a -> a -> a但在.NET中你可以添加例如TimeSpan到DateTime:

System.DateTime(2000,1,1) + new System.TimeSpan(1, 2, 0, 30, 0)

结果是DateTime,签名为:a -> b -> a

比较是一个不同的故事,因为该约束实际上存在于.NET级别,因此它可以在IL中编译和编码,而成员约束需要在编译时解决,这就是为什么函数必须标记为内联。 / p>

我认为你误解了链接问题中的解释:这不是由于性能权衡,真正的原因是.NET类型的系统限制。内联函数在大多数情况下执行得更快(因为它由编译器内联)这一事实是次要影响。