Type (synonym) families

In 2008, three years after the introduction of associated types, they were subsumed by type families. Associated types are special type families where the type function is attached to a type-class.

In contrast to associated types, we have top-level type-families that are not associated with a type-class, for example:

  type family RepF d
  type instance RepF (List' a) = (RList a)

The type family RepF represents a type function, with each instance declaring a value. Put another way, a type family represents a set of types, and each instance represents a set member.

In our example, GenericF simply uses the top-level type function in its type signatures:

class GenericF d where
  fromF :: d         -> (RepF d)
  toF   :: (RepF d)  -> d

instance GenericF (List' a) where
  fromF Nil'           = L U
  fromF (Cons' x xs)   = R (Combo x xs)

  toF (L U)            = Nil'
  toF (R (Combo x xs)) = (Cons' x xs)

main = print $ fromF (Cons' 1 Nil')

With associated types, we need to align the type function parameters with those of the type-class. Top-level type families don't have that restriction and are therefore more general than associated types. The fundamental difference between top­level and associated type families is in the scope of the type function.

Type families are to regular types what type class methods are to regular functions. Instead of polymorphism over value, type families give us polymorphism over datatypes.

As with type-classes, type families are open in the sense that we can add new instances at any time.

Type families are useful in Generic programming (as demonstrated in our example) and for writing highly-­parameterized libraries.

Data families

In our discussion of type families, we have focused on type-synonym families. However, type families can be defined for data-types as well. This lets us create families of data-types. As with type-synonym families, data-type families can be associated to a type-class or defined top-­level:

-- associated data family
class GMap k where
  data GMap k :: * -> *
  empty       :: GMap k v
  lookup      :: k -> GMap k v -> Maybe v
  insert      :: k -> v -> GMap k v -> GMap k v

-- top-level data family
data family GMap k :: * -> *
-- …

The Gmap function describes a generic interface for associative maps where the type of key k determines the type of the associated value (via the Gmap type function).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset