Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Generics Seminar Zurihac Notes -2020

Generics Seminar

Generics are about sitting between a nominal and structural view of types.

Parametric Polymorphism Vs Types Classes Vs Generics

Parametric Polymorpishm - says behave on all types in exactly same way

on the other hand typeclasses is an interface which behaves differently depending on the type

Generics are in between the two extremes

Haskell has a nominal type system - based on names

Generic programming gets the type system to behave more structurally than nominally

so Generics use associated type families to describe the structure of types by representing their data constructors in the type system.

class Generic a where 
...

data Colour = Red | Green | Blue

instance Generic Colour where 
  type Rep Colour = Either () (Either () ())
  
  -- for going to and from the values to values of the type to the values of the type for our representation of 
  -- the structure of the data types
  from :: Colour -> Rep Colour
  from Red = Left ()
  ...
  
  to :: Rep Colour -> Colour
  to ( (Left ()) = Red
  ...

-- just a marker for attaching names of data constructors to type level -- n with kind symbol - just a type level string with name of constructor
hs newtype Con (n :: Symbol) a = Con a

Once we add this new type then we rewrite the Generic instance for Colour

instance Generic Colour where 
  type Rep Colour = Either (Con "Red" ()) (Either (Con "Blue" ()) (Con "Green" ())))
  
  -- for going to and from the values to values of the type to the values of the type for our representation of 
  -- the structure of the data types
  from :: Colour -> Rep Colour
  from Red = Left ((Con ()))
  ...
  
  to :: Rep Colour -> Colour
  to ( (Left (Con ())) = Red
  ...

Now we can create a class for getting the generic constructors name GConName.

gconName just gives us the name of the data constructor which exists at the type level to the value level.

class GConName a where
  gconName :: a -> String

instance KnownSymbol n => GConName (Con n a) where
   gconName _ = symbolVal (Proxy @n)
   
instance (GConName a, GConName b) -> GConName (Either a b) where
  gconName (Left a) = gconName a
  gconName (Right b) = gconName b

Yay so we can get the name now,

This type representation so far isn't great for deriving instances through generics for parameterised types of kind * -> *

Why can't we derive all types as Generics?

GADTs and existentials are very difficult to represent as Generics

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment