I am wondering why < operator supports int, string, bool, or float, whereas + only support int.
Could OCaml recognize the underlying arithmetic to use ? What mak
There is not, at the moment, a notion of "a bit polymorphic" in OCaml (the technical name is "ad-hoc polymorphism"). You can't say "I accept integers and floats but not the rest".
You can say, however "I accept everything", just like the comparison operator (the technical name is "parametric polymorphism"). Do note however than they are lying a bit about that: you can't compare functions, even if the type system can't catch it.
See this answer for details.
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.
# 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:float) 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 (+)
)
# 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.
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.