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:float) 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)
此版本适用于 int
和 float
(以及具有静态成员 (+)
的任何其他类型(-组合))
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.
我想知道为什么 < 运算符支持 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:float) 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)
此版本适用于 int
和 float
(以及具有静态成员 (+)
的任何其他类型(-组合))
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.