{-# OPTIONS_GHC -fglasgow-exts #-} -- Examples from the second lecture (AFP_02) -- IMPORTANT: this file needs -fglasgow-exts -- eg. by calling: ghci -fglasgow-exts Classes.hs -- (with the pragma in the first line this is no longer needed) module Classes where import List import Parsing import BinTree -- III. Classes and Prelude -- define a class with a size function class HasSize a where sizeof :: a -> Int -- instantiate this class for concrete types instance HasSize [a] where sizeof = length instance HasSize (BinTree a) where sizeof (Leaf _) = 1 sizeof (Node l r) = sizeof l + sizeof r -- NB: the definitions below use multi-parameter type-classes -- these are not part of Haskell98, thus -- ghci must be started with option -fglasgow-exts -- a class using functional dependencies class (Eq b) => MyClass a b | a -> b where sizeOf :: a -> Int elemOf :: b -> a -> Bool -- NB: this instance needs the class context (Eq a) -- so that we can use the elem prelude function -- which checks for equality of elements of the -- data structure -- NB: the sizeOf function in this instance extends the -- one above by taking into account the size of the -- element type; -- this needs an additional context of (MyClass a) -- NB: @-notation: in xs@(y:ys) we define a pattern on -- lists, that only matches list cells, with head -- named y and tail named ys, and the name xs stands -- for the entire list -- (see 'as' construct in SML) -- instantiate this class for concrete types instance (Eq a, MyClass a b) => MyClass [a] a where sizeOf [] = 0 sizeOf xs@(x:_) = length xs * sizeOf x elemOf x [] = False -- could also use Prelude function elem elemOf x (y:ys) | x==y = True | otherwise = x `elemOf` ys instance (Eq a, MyClass a b) => MyClass (BinTree a) a where sizeOf (Leaf x) = sizeOf x sizeOf (Node l r) = sizeOf l + sizeOf r elemOf y (Leaf x) = x==y elemOf y (Node l r) = elemOf y l || elemOf y r instance MyClass Int () where sizeOf _ = 4 -- size in bytes, assuming wordsize of 4 elemOf _ _ = False instance MyClass Char () where sizeOf _ = 1 elemOf _ _ = False -- TESTME: -- # sizeOf ([1,2,3]::[Int]) -- 12 -- # sizeOf (['a','b','c']::[Char]) -- 3 -- IV. Lazy Evaluation foo :: Int -> Int -> Int -> Int foo x y z = if x<0 then abs x else x+y -- TESTME: -- # foo 1 2 (1 `div` 0) -- 3 nthOfInts :: Int -> Int nthOfInts n = [0..]!!n -- TESTME: -- # nthOfInts 2 -- 2