typeclass constrains
In this chapter, we will explore the following scenarios where typeclass constrains are used:
- typeclass constrains in function implementation
- typeclass constrains in class declaration
- typeclass constrains in instance implementation
typeclass constrain in functions
typeclass constrain in the function declaration:
equal3 :: forall a. Eq a => a -> a -> a -> Boolean
equal3 a1 a2 a3 = a1 == a2 && a2 == a3
a
in the function declaration is atype
, not a valueEq a
is the typeclass constrain on typea
, which means "for any typea
that has an instance of theEq
typeclass", or "there must exist anEq
instance for typea
".
typeclass constrain in class
typeclass constrain in the class signature:
data Ordering = LT | EQ | GT
class Eq a <= Ord a where
compare :: a -> a -> Ordering
- Ord is a subclass of Eq
- Eq is a superclass of Ord
📌 The class constraints in class declarations are used for making a typeclass a subclass of another typeclass.
typeclass constrain in instance
This is also called "Instance Dependencies".
The code below is from the Data.Maybe implementation:
instance showMaybe :: Show a => Show (Maybe a) where
show (Just x) = "(Just " <> show x <> ")"
show Nothing = "Nothing"
The Show
instance allows Maybe
values to be rendered as a string with show
whenever there is an Show
instance for the type the Maybe
contains.
📌 The class constraints in instance declarations are used to express requirements about the contents of some type.
The following is incorrect, because the type which will make an instance of Eq
MUST be a concrete type. Maybe
is a type constructor, it is not a concrete type, Maybe a
is a concrete type!
instance Eq Maybe where
...