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

OCaml : why comparison operator are type agnostic, whereas arithmetic ones are not?

我想知道为什么 < 运算符支持 int、string、bool 或 float,而 + 只支持 int。

OCaml 可以识别要使用的底层算法吗? 什么使比较运算符与算术运算符不同? 其他FP语言也是一样吗?

目前,OCaml 中没有 "a bit polymorphic" 的概念(技术名称是 "ad-hoc polymorphism")。你不能说 "I accept integers and floats but not the rest"。

但是你可以说"I accept everything",就像比较运算符一样(技术名称是"parametric polymorphism")。但是请注意,他们在这方面有点撒谎:您无法比较函数,即使类型系统无法捕捉它。

详情见this answer

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

它们绕过类型系统(希望我表述正确),并在运行时提供特殊支持。我建议阅读 this post 关于 OCaml 多态比较的内容。

比较运算符 <><>= 具有相同的签名:

'a -> 'a -> bool

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

函数的类型less

let less a b = a < b

自动扣除为

val less : 'a -> 'a -> bool = <fun>

同时,return 算术运算符类型取决于参数类型:

# let plus a b = a + b;;
val plus : int -> int -> int = <fun>

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

F#

# let plus a b = a + b
val plus : a:int -> b:int -> int

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

# let plus (a:fl­oat) b = a + b
val plus : a:float -> b:float -> float

如果你加上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)

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

Haskell

# let plus a b = a + b
plus :: Num a => a -> a -> a

Return 和 plus 函数的参数类型自动推断为 Num 类型的任何类型 class。这意味着 plus 是真正的多态,可以与 int、float 和其他数字类型一起使用。

OCaml

因此,它可以是另一种特殊情况(如在 F# 中),或功能齐全的解决方案,如 Haskell 的类型 classes。我投后者。

a fork of OCaml that addresses this problem by extending it with modular implicits.