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?
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++.
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.
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, eg
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.