8

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 ?

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
Pierre G.
  • 4,346
  • 1
  • 12
  • 25
  • 2
    I can only comment on the last question: no it's not - for example in F# (which is like a little cousin to Ocaml) `+` is overloaded - Haskell is using typeclasses and languages like Scheme don't have the need at all as they are dynamical typed - to be honest right now I can think of no other language than Ocaml where you have to decide between `+` and `+.` – Random Dev Oct 29 '15 at 11:46
  • 1
    Please see the video at https://www.irill.org/videos/oups-december-2014/Modular_implicits where main 'problem' is explained in the beginning. – Str. Nov 05 '15 at 21:53

2 Answers2

8

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.

Drup
  • 3,679
  • 13
  • 14
6

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.

Stas
  • 11,571
  • 9
  • 40
  • 58
  • @Carsten Thanks a lot! I didn't know about this feature. – Stas Oct 29 '15 at 17:50
  • Note that certain values are not comparable (for example, functions). Comparison operators raise an exception when you try to compare such values – copy Oct 30 '15 at 15:41