OCaml:为什么比较运算符是类型不可知的,而算术运算符不是?

Pie*_* G. 8 ocaml functional-programming

我想知道为什么<operator支持int,string,bool或float,而+只支持int.

OCaml可以识别要使用的基础算术吗?什么使比较运算符与算术运算符不同?其他FP语言是否相同?

Dru*_*rup 7

目前,OCaml中没有"有点多态"的概念(技术名称是"ad-hoc多态性").你不能说"我接受整数和漂浮而不是其余的".

你可以说,"我接受一切",就像比较运算符(技术名称是"参数多态").但要注意的是,他们有点说谎:你无法比较函数,即使类型系统无法捕获它.

有关详情,请参阅此答案.


Sta*_*tas 6

比较运算符在OCaml中是特殊的.他们能够递归地比较记录,变体类型,列表和其他数据结构.

他们绕过一个类型系统(希望我把它制定得正确),并在运行时有一个特殊的支持.我建议阅读这篇关于OCaml多态比较的文章.

比较运营商<,>,<>,=具有相同的签名:

'a -> 'a -> bool
Run Code Online (Sandbox Code Playgroud)

bool无论输入参数的类型如何,它们总是返回.因此,这些运算符可能具有多态行为,并且不需要类型系统的类型推断的额外支持:

功能的类型 less

let less a b = a < b
Run Code Online (Sandbox Code Playgroud)

自动扣除

val less : 'a -> 'a -> bool = <fun>
Run Code Online (Sandbox Code Playgroud)

同时,算术运算符的返回类型取决于参数的类型:

# let plus a b = a + b;;
val plus : int -> int -> int = <fun>
Run Code Online (Sandbox Code Playgroud)

看,a + b在多态+运算符的情况下,你不能自动推断表达式.应扩展类型系统以支持此功能.

F#

# let plus a b = a + b
val plus : a:int -> b:int -> int
Run Code Online (Sandbox Code Playgroud)

它被int默认扣除.为了能够plus为浮点数编写函数,您需要向输入参数中的至少一个添加显式类型注释:

# let plus (a:fl­oat) b = a + b
val plus : a:float -> b:float -> float
Run Code Online (Sandbox Code Playgroud)

如果添加,inline您可以获得更多:

# let inline plus a b = a + b
val inline plus :
  a: ^a -> b: ^b ->  ^c
    when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^c)
Run Code Online (Sandbox Code Playgroud)

此版本适用于intfloat(以及具有静态成员的任何其他类型(-combination)(+))

哈斯克尔

# let plus a b = a + b
plus :: Num a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

plus函数的返回和参数类型会自动推断到任何类型的Num类.这意味着它plus是真正的多态,可以与int,float和其他数字类型一起使用.

OCaml的

因此,它可能是另一个特殊情况(如F#),或者像Haskell类型类这样的全功能解决方案.我投票支持后者.

一个 OCaml 的分支通过使用模块化含义扩展它来解决这个问题.