Types F中的添加类型(+;)#

Types F中的添加类型(+;)#,types,f#,ocaml,inline,Types,F#,Ocaml,Inline,我刚刚了解到,OCAML必须有一个后缀才能进行浮点运算。例如3.+。4.等于7.(浮动)。但是,F#以相同的方式处理浮点和整数运算,因此3+4(int)和3.+4.(浮动)有效 F#将+自然分配给int,因此让我们添加一个b=a+b类型为int->int->int。实际上,(+)给了我valit:(int->int->int)= 这导致了以下顺序,我认为这与直觉是背道而驰的: > 3. + 4.;; val it : float = 7.0 > (+);; val it : (int

我刚刚了解到,OCAML必须有一个
后缀才能进行浮点运算。例如
3.+。4.
等于
7.
(浮动)。但是,F#以相同的方式处理浮点和整数运算,因此
3+4
(int)和
3.+4.
(浮动)有效

F#将
+
自然分配给int,因此
让我们添加一个b=a+b
类型为
int->int->int
。实际上,
(+)
给了我
valit:(int->int->int)=

这导致了以下顺序,我认为这与直觉是背道而驰的:

> 3. + 4.;;
val it : float = 7.0
> (+);;
val it : (int -> int -> int) = <fun:it@8-2>
>3+4.
val it:float=7.0
> (+);;
val it:(int->int->int)=
所以我的问题是:“重载”是由编译器中的一种特殊机制/用例完成的,还是这是一种语言范围内的事情,这样我就可以定义一个名为
add
(或任何其他)的函数,它有一个整数定义,一个浮点数定义(或任何其他类型)。

重载函数(和运算符)必须在F#中标记
inline
。这是因为他们依赖于。这些约束在编译时得到解决。函数
let inline add A b=A+b
的类型为
'A->'b->'c(需要成员(+))
,其中
+
是静态函数/运算符。你不能用C#做这件事;它没有静态成员约束

let inline add a b = a + b
add 1 2 //works
add 1.0 2.0 //also works
简单地说,F#通过
inline
关键字和“静态成员约束”具有一种特殊的重载机制。内置数学运算符还有一些特殊的魔力,它神奇地假设type
int
没有其他约束
(+)
几乎是所有F#中最特别/最神奇的东西,因此它不能很好地介绍语言/类型系统


通常,“重载”对于静态类型的、类型推断的语言来说是困难的。F#在这里的选择非常务实。OCaml做了一件不同的、简单的、实用的事情(没有重载)。Haskell做了一件不同的、复杂但优雅的事情(类型类)。这些都是语言/库设计空间中的合理点。

除了Brian的答案和链接之外:

我在代码中找到了一些定义:

let inline (+) (x:int) (y:int) = (# "add" x y : int #)


工作,并给出3作为输出(警告说您不应该这样做)。

您可能对以下内容感兴趣:@Daniel编译时类型约束。很好,谢谢:)然而,问题仍然存在:在F#中是这样做的吗?我不确定我是否明白。泛型函数只能写
内联
,如果这是您所要求的。+1酷:)我从它使用编译类型约束的函数类型中看出。然而,这并不能完全回答这个问题。当
(+)
对这两个成员都有效时,它的定义到底是什么?类似于:
'a->'b->'c(需要成员(+))
这意味着,它适用于任何具有静态成员的类型
(+)
。什么是
(+)
?:)它告诉我它是
int->int->int
,但它在float上工作,为什么?如果不清楚我的意思,我很抱歉:/你可以在这里看到代码:这是血淋淋的,你不想知道细节。其中一些是针对内置数学运算符的特定编译器魔法。更一般地说,您可以使用
内联
和静态成员约束在用户代码中执行类似的duck键入操作,但这也很麻烦,您不想知道细节。简短的回答是:“魔法”。@lass:它的类型是
int->int->int
,除非您将其标记为
inline
。因此,是的,F#在默认情况下似乎选择
int
,除非它可以根据用法推断出更好的类型(例如,如果您对函数的初始调用使用浮点参数)。谢谢,注释中的链接和描述就是我所需要的:)是的,FSharp.Core库有一些魔力,可以在没有.NETAPI的情况下访问底层IL构造。你不应该在你自己的代码中使用
(#…#)
的东西,编译器没有完全拒绝这是一个错误(编译器的未来版本将完全拒绝它)。@Brian:为什么我们不能编写内联IL?这不是一只虫子;这是一个特性。:-)
let inline (+) (x: ^T) (y: ^U) : ^V = 
     AdditionDynamic<(^T),(^U),(^V)>  x y 
     when ^T : int32       and ^U : int32      = (# "add" x y : int32 #)
     when ^T : float       and ^U : float      = (# "add" x y : float #)
     when ^T : float32     and ^U : float32    = (# "add" x y : float32 #)
     ...
(# "add" 1 2 : int32 #)