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

后端 未结 2 1548
不知归路
不知归路 2021-01-12 04:55

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

相关标签:
2条回答
  • 2021-01-12 05:31

    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.

    0 讨论(0)
  • 2021-01-12 05:33

    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.

    0 讨论(0)
提交回复
热议问题