====== 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~~