====== Type classes and its instances, and the deriving mechanism ====== * A type class (keyword: ''class'') is a set of functions declarations that * can have generic default bindings, and * have instances (keyword: ''instance'') with type specific bindings. * module ''Prelude'' already consists of many type classes * {{:modules:preludetypeclasses.png?direct&300|}} * picture from: Dirk Hünniger * source: [[https://commons.wikimedia.org/wiki/File:HaskellClasses.svg]] * type ''class''es are in bold * below all types that have implemented instances * e.g. type ''class'' ''Num'' has implemented ''instance''s for the following types * ''Int'' * ''Integer'' *'' Float'' * ''Double'' * additionally, there is many other libraries available with important type classes * {{:codesnippets:typeclassopedia-diagram.png?direct&700|}} * source: [[https://wiki.haskell.org/Typeclassopedia]] * example, implementing an ''Enum'' type class, and an instance for a data type * functions ''succ'', and ''pred'' have default implementations in ''class Enum'', * which have been overridden in the ''instance Enum MyInt'' of * code: import Prelude hiding (Enum(..)) main :: IO () main = putStrLn (show x1) class Enum a where succ, pred :: a -> a succ = toEnum . (+ 1) . fromEnum pred = toEnum . (subtract 1) . fromEnum toEnum :: Int -> a fromEnum :: a -> Int data MyInt = C0 | C1 | C2 | C3 instance Enum MyInt where toEnum 0 = C0 toEnum 1 = C1 toEnum 2 = C2 toEnum 3 = C3 fromEnum C0 = 0 fromEnum C1 = 1 fromEnum C2 = 2 fromEnum C3 = 3 succ C3 = C0 succ x = (toEnum . (+ 1) . fromEnum) x pred C0 = C3 pred x = (toEnum . (subtract 1) . fromEnum) x x1 = fromEnum (succ (succ (succ C3))) * executes, with output: 2 * example, implementing a ''Show'' type class, and an instance for a data type * function ''show'' is implemented to covert every possible value of ''MyInt'' into a ''String'' * code: import Prelude hiding (Show(..)) main :: IO () main = putStrLn (show x1) class Show a where show :: a -> String data MyInt = C0 | C1 | C2 | C3 instance Show MyInt where show C0 = "C0" show C1 = "C1" show C2 = "C2" show C3 = "C3" x1 = C3 * executes, with output: C3 * example, implementing an ''instance'' of the ''Prelude'' class ''Show'' for a data type * function ''show'' is implemented again for ''MyInt'' * code: main :: IO () main = putStrLn (show x1) data MyInt = C0 | C1 | C2 | C3 instance Show MyInt where show C0 = "C0" show C1 = "C1" show C2 = "C2" show C3 = "C3" x1 = C3 * executes, again with output: C3 ===== Deriving mechanism ===== Looking to the examples above you may wonder, whether there an easier way to implement an ''instance'' of standard type classes. Yes, there is the ''deriving'' mechanism. * example, where a data type applies ''deriving'' mechanism * to implement all function of typeclass ''Show'', and ''Enum'' * code: main :: IO () main = putStrLn (show x1) data MyInt = C0 | C1 | C2 | C3 deriving (Show, Enum) x1 = succ C1 * executes, again with output: C2 ===== Advanced type classes ===== * example, implementing a ''Functor'' * code: import Prelude hiding (Maybe(..), Functor(..)) main :: IO () main = do print x1 class Functor f where fmap :: (a -> b) -> f a -> f b data Maybe a = Just a | Nothing deriving Show instance Functor Maybe where fmap f (Just x) = Just (f x) fmap _ Nothing = Nothing x1 = fmap (+3) (Just 2) * executes, with output: Just 5 ===== ✎ ===== ~~DISCUSSION~~