4 ms·
It was a surprising language decision to find out that OCaml didn't do implement polymorphic behaviour for common operations and opted to stress static types fo
by djtango 8y ago
It was a surprising language decision to find out that OCaml didn't do implement polymorphic behaviour for common operations and opted to stress static types for things like print_int or 1.0 +. 1.0...
- k__ 8y agoDoes this mean, it has a special function/operator for adding ints to floats?
- masklinn 8y agoIt doesn't have any way to add ints to floats directly. You have to convert one to the other then perform the addition. Haskell or Rust are the same incidentally: while the same "lexical" operator is used all the time (`+`), numeric additions are defined for two values of the exact same concrete type e.g. in Haskell you can add two Int or to Float or two Integer, but not an Int and an Integer, or an Int and a Float: Prelude> (1::Int) + (1::Int) 2 Prelude> (1::Integer) + (1::Integer) 2 Prelude> (1::Float) + (1::Float) 2.0 <interactive>:6:15: error: • Couldn't match expected type ‘Float’ with actual type ‘Int’ • In the second argument of ‘(+)’, namely ‘(1 :: Int)’ In the expression: (1 :: Float) + (1 :: Int) In an equation for ‘it’: it = (1 :: Float) + (1 :: Int)
- watshn 8y agoWhile true, that issue arose because you restricted their types. Without the type annotations it would have worked just fine, because the (+) function is polymorphic in the Num typeclass, and because literals are overloaded such that the literal 1 will have type Fractional a when type inference calls for it. So in ghci: Prelude> let x = 1 + 1.0 Prelude> :t x x :: Fractional a => a Prelude> x 2.0
- masklinn 8y ago> While true, that issue arose because you restricted their types. What I was intending to show occurred because I engineered the example to show it, yes, that was the entire point. > Without the type annotations it would have worked just fine Without the type annotation it would have been in an actual codebase rather than the REPL, and that codebase would have been typed. > because the (+) function is polymorphic in the Num typeclass, and because literals are overloaded such that the literal 1 will have type Fractional a when type inference calls for it. Which does not contradict my point at all. > So in ghci: Which works because (drumroll) both operands are of the same Fractional type. Which is the entire point of my comment: Haskell does not allow adding numbers of different types with one another any more than OCaml does.
- RussianCow 8y agoIt has a separate operator for adding two floats: +.
- rwmj 8y agoOne reason is that promotion from int to float is not free! Therefore maybe it should be explicit that your code is doing that especially in a language like OCaml that cares a lot about performance and is used in a few performance-sensitive areas (notably HFT).
- christophilus 8y agoYou can have overloaded functions without having type promotions. `1 + 2` would call `addInt`, `1.0 + 2.0` would call `addDouble` and `1 + 2.0` would be a type error, requiring manual conversion in order to fix it.
- wyoung2 8y ago> promotion from int to float is not free! Nor is it safe to allow implicit conversion in general, but F# shows that you don’t need separate operators for floating point. You just need a compiler that refuses to implicitly convert data types, as F# does, so you must use explicit conversions and type suffixes if you want to mix data types. If you manually convert, then on your head be the consequences. This is not legal F#: let x = 1.0 + 1 But both of these are legal: let x = 1.0 + 1.0 let y = 1.0 + float 1 F# doesn’t even let you mix single- and double-precision FP: let x = 1.0f + 1.0 // ILLEGAL let x = 1.0f + float32 1 // legal
- ernst_klim 8y agoAnd both F# and sml have a problem with that. What type should this function have: let add x y = x + y The proper solution for ad-hoc polymorphism is either dynamic dispatching (aka oop solution) or type-classes or OCaml's modular implicits, not ad-hoc monkey patches like that. And I find (+.) fine since float addition is not an arithmetic addition.
- wyoung2 8y ago> What type should this function have: If you don't call it, F# simply guesses "int -> int -> int". If you pass a float, you get back a curried function taking float and returning float. Now that the "add" function's type is known, you now can't pass an int: that's now known to be an error. Seems sensible to me. No problem.
- masklinn 8y agoIsn't it because "constrained" polymorphism goes through functors? And that wouldn't be very convenient for such basic operations?