Associated Type Synonyms in Haskell
Post explores the basic idea behind Type Synonyms in Haskell
Type families in Haskell enable type resolution based on other types. Type families mirror typeclasses (which resolve function implementations based on types). Let’s write two records - a person and an animal:
data Person = Person { name :: String} deriving Show
data Animal = Animal { species :: String} deriving Show
aPerson :: Person
= Person { name = "Jan" }
aPerson
anAnimal :: Animal
= Animal { species = "dog" } anAnimal
Let’s now suppose that each record lives in a different environment - an Animal
is always in a Wilderness
and a Person
is in a House
,
data House = House Person deriving Show
data Wilderness = Wilderness Animal deriving Show
We now come to the crux of the matter. We want to write a function env
which places each entity into the right environment - a Person
into the House
and an Animal
into the Wilderness
. How do we do that? Let’s solve a simpler problem first - let’s write env
which places a Person
into a House
, that is the argument of env
is a Person
and the output is the proper environment for the person (i.e. a House
).
env :: Person -> House
= House p
env p
print $ env aPerson
Which gives us the output House (Person {name = "Jan"})
. But now we want to extend the env
function such that we can call print $ env anAnimal
. This can be done by a typeclass, but what would be the type signature of env
?
class Environment a where
env :: a -> ???
This is where type families come in. We can use an associated type synonym (we can call it Env
) and define the return type of env
in the instances of the typeclass.
class Environment a where
type Env a :: *
env :: a -> Env a
This definition says that we have a
associated type synonym Env a
where the result type is chosen according to the type variable a
. All we need to do now is to write the instances:
instance Environment Person where
type Env Person = House
= House
env
instance Environment Animal where
type Env Animal = Wilderness
= Wilderness env
For each instance we define the type synonym. For example Env Person = House Person
in the first instance and Env Animal = Wilderness Animal
in the second instance. We can test the implementation by printing the following:
= do
main print $ env anAnimal
print $ env aPerson
We get:
"Wilderness (Animal {species = "Dog"})"
"House (Person {name = "Jan"})"