This is an old revision of the document!
6. Classes in Haskell
Last time we've learned how to define our new data types in Haskell. The simpler ones were Ordering
(some “constants”), Point Float Float
, and Student String String [Float]
.
We've seen that we can define recursively monomorphic or polymorphic types, like List a
and BTree a
.
Today we will use the following data:
data List a = Null | Cons a (List a) data BTree a = Void | Node a (BTree a) (BTree a) data Student = Student { first_name :: String, last_name :: String, grades :: [Float] } {-- For Student, we can define it as a 'struct Student' from C. first_name will be a "getter" for our first String. Haskell helps us by defining 3 simple functions for us to extract each member Try :t Student and :t first_name in GHCI and you'll figure it out quickly. --}
Now let's check one more interesting concept, Haskell's class system.
If data can be considered the class from Java, then class
could be considered the interface from Java.
If you're defining a new data Point, you probably encountered some problems trying to print it in GHCI.
The quick fix would be adding the deriving Show
, which will print the data type in a 'default' manner (you can try).
But what exactly is this Show
? And how can we provide our Show?
We can look at the Show class in a simplified form:
class Show a where show :: a -> String
Here a
is a data. More precisely, to be able to print any data from Haskell, then it must implement the show function. That's why we can consider it an interface.
Providing our show will be done by enrolling our type in the already existing class Show. Here you have a simple example, in the lab skel you'll see a more complex show, just for flexing.
-- the type encapsulated in BTree must also be "showable", so we can do (show v) instance (Show a) => Show (BTree a) where show Void = "" show (Node v l r) = "<"++(show l)++(show v)++(show r)++">"
1. Add List and Student to the Show class. You can print them however you want. If you aren't inspired today, you can use the following:
- The lists can be the default style → [1,2,3].
- The student can be something like → Studentul: ANDREI Alex-Bogdan = [8.5,6.0,8.7]
2. The default ==
that we get from deriving Eq will check if 2 objects are identical. For our data, you'll have to provide a custom '==' such that:
- list1 == list2 = True if both trees have the same elements, but in any order
- tree1 == tree2 = True if both trees have the same elements, but in any order
- stud1 == stud2 = True if both students have the same average on their grades
3. We would like to use +
and *
on lists and trees to add/multiply corespondent elements. If 2 lists or trees aren't at the same size, then we should consider unexisting corespondents as Null/Void. Also
- Void + Node = Node
- Void * Node = Void
- same for lists
4. Let's sort students now. Add the student to the Ord class and provide implementations for <
. The criteria will be their grades average, maximum grade, last_name, and first_name alphabetical.