1. The Easy Part
  2. Higher Order Functions
  3. Types
  4. Lists
  5. Complex Data Objects
  6. File IO
  7. Classes
  8. Monads
  9. List Monads
  10. Shared Transactional Memory

Classes

Operator Overloading

Classes are a mechanism used to allow the same function or operator to be used on objects of different type.

In this trivial example, we implement our own version of the equals class, and call it 'equ'.

mc.hs
1-- here's the class we are defining
2class Foo a where
3    equ :: a -> a -> Bool
4 
5-- here are two data types who are members
6-- of the class
7data Bar = Barc Integer
8data Baz = Bazc Double
9 
10-- helper methods
11ubarc (Barc a) = a
12ubazc (Bazc a) = a
13 
14-- make Bar an instance of Foo
15instance Foo Bar where
16    equ a b = (ubarc a) == (ubarc b)
17 
18-- make Baz an instance of Foo
19instance Foo Baz where
20    equ a b = (ubazc a) == (ubazc b)
21 
22-- create some data
23t1 = Barc 3
24t2 = Barc 4
25t3 = Bazc 1.0
26t4 = Bazc 1.0
27 
28main = do
29    putStrLn(show(t1 `equ` t2))
30    putStrLn(show(t3 `equ` t4))
$ ghc --make mc.hs
[1 of 1] Compiling Main             ( mc.hs, mc.o )
Linking mc ...
$ ./mc
False
True

Using the Built-In Eq Class

Here we define a type called Foo and make it an instance of equ.

mc2.hs
1data Foo = Bar Int
2 
3instance Eq Foo where
4    (==) (Bar a) (Bar b) = (a == b)
5 
6main = putStrLn(show((Bar 3) == (Bar 4)))
$ ghc --make mc2.hs
[1 of 1] Compiling Main             ( mc2.hs, mc2.o )
Linking mc2 ...
$ ./mc2
False

Fortunately, there is a far easier way of doing this that does what we want 99% of the time:

mc3.hs
1data Foo = Bar Int
2    deriving Eq
3 
4main = putStrLn(show((Bar 3) == (Bar 4)))
$ ghc --make mc3.hs
[1 of 1] Compiling Main             ( mc3.hs, mc3.o )
Linking mc3 ...
$ ./mc3
False