
On 12/03/2013, at 3:15 AM, Carlos Camarao wrote:
Hi,
I just started playing around a bit with Haskell, so sorry in advance for very basic (and maybe stupid) questions. Coming from the C++ world one thing I would like to do is overloading operators. For example I want to write (Date 6 6 1973) + (Period 2 Months) for some self defined types Date and Period. Another example would be (Period 1 Years) + (Period 3 Months).
Just defining the operator (+) does not work because it collides with Prelude.+. I assume using fully qualified names would work, but that is not what I want.
Hi. To define (+) as an overloaded operator in Haskell, you have to
define
and use a type class.
Stop right there. Overloading in the C++ sense is "ad hoc polymorphism" where the signatures of the various definitions need not resemble each other in any way. Haskell just plain does not have anything like that. (+) in Haskell is *not* overloaded; it has several implementations and allows you to define as many more as you want. But they all conform to the *SAME* interface. This is much more like OO inheritance.
Sorry, I think my sentence: "To define (+) as an overloaded operator in Haskell, you have to define and use a type class." is not quite correct. I meant that to define any operator in Haskell you have to have a type class defined with that operator as member. Then, if there is already a type class defined, a programmer can either use it (if that is suitable/adequate) or hide it and define another one. Sorry, that's what I meant.
In particular, C++ will let you define versions of + where the arguments are of two different types and the result is a third. You cannot provide such an implementation for Haskell's predefined (+).
Yes, but the requirement of using the "predefined" (+) is an extra requirement (I would call (+) in Haskell not a predefined operator, but an operator whose type is defined in a class (Num) which is in the Prelude). A Haskell programmer can still define versions of (+) where the arguments are of two different types and the result is a third (he cannot though use the two type classes, and thus neither instances of these two type classes, in a program). The suitability/adequacy of the type defined in a class means that the type of all names/operators in an instance of the class must be an instance-type of the type specified in the class. And unsuitability/inadequacy requires the definition and use of another type class (sorry to repeat that, just reinforcing).
Furthermore, Haskell supports a more powerful form of overloading than (any other language I know, including) C++: context-dependent overloading. This means that the type of an expression (f e), and thus of f, can be determined at compile-time (inferred) based on the context where (f e) occurs, not only on the type of the argument (e) of the function's call.
Ada has had this since Ada 81. The design goal that forced it was the wish to allow the same identifier to be used as an enumeral in more than one enumerated type, so that you could do type Colour is (Red, Green, Blue); type Fruit_State is (Green, Ripe, Rotten); X : Colour := Green; Y : Fruit_State := Green;
and in particular, since character literals like 'X' are allowed as enumerals in Ada, they wished to be able to write A: EBCDIC_Character := 'X'; B: ASCII_Character := 'X'; and have A and B be different bytes. The difference is that Ada *does* do this sort of thing using overload resolution and Haskell *doesn't*.
Ok. I will have a look at Ada's overloading mechanism. Thanks! I am trying to emphasize the constrained *polymorphism* that is possible in Haskell, which allows overloading resolution not to be required in an use of an operator or constant. I believe that this is a significant new contribution of the language. (I think Green and 'X' are not polymorphic, and any use of them required thus that overloading be resolved).
For example, you _could_ in principle use (d+p==d) and (d+p==p), with d::Date, p::Period, and instances of (+) with types Date->Period->Date and Date->Period->Period, if you wish… Prelude> :type (+) (+) :: Num a => a -> a -> a The predefined (+) in Haskell requires its arguments and its result to be precisely the same type.
I think you had better justify the claim that Date+Period -> Date and Date+Period -> Period are possible at the same time by showing us actual code.
I think I have shown it (see previous message): as Miguel Mitrofanov, hiding and redefining Num. Kind regards, Carlos