3

I am learning Haskell. When I gone through following documentation. https://www.haskell.org/tutorial/classes.html

It is mentioned that "Haskell does not support the C++ overloading style in which functions with different types share a common name." I am not getting this statement, I guess ad-hoc polymorphism (which is done by using type classes) is equivalent to method overloading in C++, Java. Can some body explain me is my understanding correct ?

class Equal a where

    isEquals :: a -> a -> Bool


type Id = Int
type Name = String

data Employee = Engineer Id Name 

data Student = Student Id Name

getEmpId (Engineer empId _) = empId
getStudId (Student studId _) = studId

instance Equal Employee where
    isEquals emp1 emp2 = getEmpId emp1 == getEmpId emp2

instance Equal Student where
    isEquals stud1 stud2 = getStudId stud1 == getStudId stud2

In the above snippet 'isEquals' function is applied to two different types Employee, Student which is equivalant of overloading in C++, Java. Is my understanding correct?

1
  • There is only one isEquals function - its type is Equal a => a -> a -> Bool. Typeclasses give you much more power than method overloading, so to say they are "equivalent" is wrong. Already your Equals class precludes isEquals :: Int -> Char -> Bool which is something you cannot get from simple method overloading. Haskell typeclasses are more similar to OO interfaces - where you define a specification in advance which can be implemented by multiple types (although there are again plenty of differences). Commented Apr 14, 2016 at 15:23

3 Answers 3

2

Partially, yes. However, keep in mind that signature of your isEquals is always a -> a. In C++ you could easily write:

int foo(int a, int b)
int foo(int a, char b)
int foo(char a, char b)

By using typeclasses you're only able to get first and third function, never the second.

UPDATE 1:

as noted in comments, you can achieve the second version by using MultiParamTypeClasses extension (if you're using GHC). Still, there is fourth version:

int foo(int a, int a, int a)

which has wrong arity if you use a typeclass, but is perfectly fine in C++.

Sign up to request clarification or add additional context in comments.

6 Comments

I guess we can achieve 'int foo(int a, char b)' using by enabling Haskell extension 'MultiParamTypeClasses'.
@HariKrishna exactly, and here's an example. Or actually, a much simpler one
certainly, but first, it's an extension, second - you still have a sigle decision point of how many types are there and third - there is always a constant amount of arguments, which is not guaranteed by C++
The typeclass also prevents you (I think) from overloading on arity. A multi parameter type class would allow you to define int foo(int a, char b), but I don't think it helps you define int foo(int a, int b, int c).
@chepner Well, one could be enable a bunch of extensions and use class C a where foo :: a and instance C (Int -> Char -> Int) where .... This can "work" if foo is used in the right contexts, but it can require some annotations in others. For variadic functions there's also the printf hack. All of this is not very idiomatic, and should be avoided if possible, IMHO.
|
0

Type classes in Haskell are just a fancy way of providing implicit arguments. Consider this code:

data Equal a = Equal {isEquals :: a -> a -> Bool}


type Id = Int
type Name = String

data Employee = Engineer Id Name 

data Student = Student Id Name

getEmpId (Engineer empId _) = empId
getStudId (Student studId _) = studId

equalEmployee :: Equal Employee
equalEmployee = Equal {
    isEquals = \emp1 emp2 -> getEmpId emp1 == getEmpId emp2
}

equalStudent :: Equal Student
equalStudent = Equal {
    isEquals stud1 stud2 = getStudId stud1 == getStudId stud2
}

equalThree :: Equal a -> a -> a -> a -> Bool
equalThree e a1 a2 a3 = isEquals e a1 a2 && isEquals e a2 a3

What is the difference with your code? Well, if in your code we define

equalThree :: Equal a => a -> a -> a -> Bool
equalThree a1 a2 a3 = isEquals a1 a2 && isEquals a2 a3

The difference is that in your code (with classes) compiler finds a suitable class instance by itself, using given types. In my variant, required instances are provided explicitly. But that's the only difference; in fact, your variant would be converted to mine under the hood.

So, classes do not override anything. They are just a fancy syntax for data types and implicit arguments.

Comments

0

Not really. The only way to get the equivalent of C++ (function; Haskell has no methods!) overloading would be a type class

class SomeFunc a where
    someFunc :: a

Now you can define someFunc at (more or less) any type you want. But you would have to declare it for every function you want to 'overload', whereas in C++ it's implicit simply from having two functions with the same name.

Haskell's type system is designed to provide something C++'s doesn't: standardized behavior (expressed as laws). So, for example, the standard Prelude defines

class Eq a where
    (==), (/=) :: a -> a -> Bool

and now you know every == operator in the language takes two arguments, of the same type, and returns a boolean; by contrast, C++ is perfectly fine with something like

mystring operator (==)(mystring x, string y) {
    return x + " == " + y;
}

that breaks all of those 'reasonable' rules. Beyond that, type classes come with laws, e.g.

x == x = True -- x total
x == y = y == x
x == y = True => y == z = True => x == z = True

which are additional restrictions on all instances. That's made a lot easier by the fact that every instance is an instance of this type class (defined in one place), which gives you a single place to define what those laws are. In C++, such 'laws' have more of the character of conventions. Furthermore, C++ is explicitly designed to allow things like using + for string concatenation, while Haskell is explicitly designed to dis-allow things like that (that's what 'Haskell does not supporth the C++ overloading style' probably means), so laws have to have more of the character of conventions in C++, which individual types can ignore if it's convenient for them.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.