Type Classes
12.1 Using and Deriving Standard Classes
compare, <, max, min Convert to a String (debug representation) Parse from a String succ, pred, [a..] Min/max values minBound, maxBound
Num, Integral, Fractional, Floating Semigroup, Monoid <>, mempty Functor, Applicative, Monad Structure-preserving mapping, effects fmap, pure, <*>, >>= Foldable, Traversable Reducing and traversing containers foldr, traverse
12.2 Defining Type Classes and Instances
Laws: many classes have laws (e.g., Eq reflexivity, Ord transitivity, Monoid associativity) that instances should satisfy. The compiler doesn't check them, so test them with QuickCheck.
Coherence: at most one instance per type per class. Avoid orphan instances (instances defined in a module that owns neither the class nor the type).
class Shape a where
area :: a -> Double
perimeter :: a -> Double
describe :: a -> String
describe x = "Shape with area " ++ show (area x) -- default implementation
data Circle = Circle Double
data Square = Square Double
instance Shape Circle where
area (Circle r) = pi * r * r
perimeter (Circle r) = 2 * pi * r
instance Shape Square where
area (Square s) = s * s
perimeter (Square s) = 4 * s
describe s = "A square of area " ++ show (area s) -- override the default
-- Manual instances of standard classes
data Suit = Hearts | Spades deriving (Eq)
instance Show Suit where
show Hearts = "♥"
show Spades = "♠"
data Version = Version Int Int deriving (Eq)
instance Ord Version where
compare (Version a b) (Version c d) = compare (a, b) (c, d)
-- Instances with constraints
data Box a = Box a
instance Show a => Show (Box a) where
show (Box x) = "Box(" ++ show x ++ ")"
-- Superclasses: every Entity must also be Eq and Show
class (Eq a, Show a) => Entity a where
entityId :: a -> Int12.3 Type Classes vs OOP Interfaces
Type classes dispatch on types (including the return type: read, mempty, pure) rather than on an object. Instances can be added to existing types after the fact, and they can be conditional (instance Show a => Show [a]).