OCaml:为什么比较运算符是类型无关的,而算术运算符不是? [英] OCaml : why comparison operator are type agnostic, whereas arithmetic ones are not?

查看:94
本文介绍了OCaml:为什么比较运算符是类型无关的,而算术运算符不是?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

解决方案

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

它们绕过类型系统(希望我正确地定义了它),并且在运行时具有特殊的支持.我建议阅读有关OCaml多态比较的这篇文章. >

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

'a -> 'a -> bool

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

函数的类型less

let less a b = a < b

会自动扣除为

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

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

# 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

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

OCaml

因此,它可能是另一种特殊情况(例如F#中的情况),或者是功能全面的解决方案(例如Haskell的类型类).我为后者投票.

OCaml的 fork 可通过使用模块化隐式.

I am wondering why < operator supports int, string, bool, or float, whereas + only support int.

Could OCaml recognize the underlying arithmetic to use ? What makes comparison operator different from arithmetic ones ? Is it the same for other FP language ?

解决方案

Comparison operators are special in OCaml. They are able to compare records, variant types, lists and other data structures recursively.

They by-pass a type system (hope I formulated it correct), and have a special support in runtime. I would recommend to read this post about OCaml polymorphic comparison.

Comparison operators <, >, <>, = have the same signature:

'a -> 'a -> bool

And they always return bool regardless of type of input arguments. So, these operators may have polymorphic behavior and don't require additional support by type system for type inference:

The type of the function less

let less a b = a < b

is automatically deducted to

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

At the same time, return type of arithmetic operators depends on type of arguments:

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

See, you can't automatically inference type of a + b expression in case of polymorphic + operator. Type system should be extended to support this.

F#

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

It is deducted to int by default. To be able to write plus function for floats, you need to add explicit type annotation to at least one of input argument:

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

If you add inline you can get even more:

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

This version will work for both int and float (and any other type(-combination) that has a static member (+))

Haskell

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

Return and argument types of plus function are automatically inferred to any type of Num type class. It means that plus is truly polymorphic and can be used with ints, floats and other numeric types.

OCaml

So, it can be yet another special case (like in F#), or full-featured solution like Haskell's type classes. I vote for the latter.

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

这篇关于OCaml:为什么比较运算符是类型无关的,而算术运算符不是?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆