We can use pair sequences to create heterogenous lists in Haskell:
type a *: b = (a, b)
a *: b = (a, b)
infixr 5 *:
hlist :: Int *: String *: Maybe Float *: ()
hlist = 1 *: "hello" *: Just 3 *: () -- (1, ("hello", (Just 3, ())))
Is there a way we can do type-level filtering on these lists? That is, define some polymorphic function hfilter such that for distinct types a, b, and c:
hfilter :: a *: b *: c *: a *: b *: a *: () -> a *: a *: a *: ()
hfilter :: a *: b *: c *: a *: b *: a *: () -> b *: b *: ()
hfilter :: a *: b *: c *: a *: b *: a *: () -> c *: ()
hfilter :: a *: b *: c *: a *: b *: a *: () -> ()
It’s possible with a few type extensions (as an aside, please check that your example code compiles when posting questions. I had to make quite a few corrections).
Now we can filter items by type by explicitly defining the type of the list we want.
It works by defining a multi-parameter type-class
TypeFilter, which takes the type of the heterogenous list and the type we want to filter by. We then define instances for the empty list/unit()and for a list where the type matches (TypeFilter (t :* rest) t) and finally for a list where the type of the head is different than the type we want to retrieve (TypeFilter (a :* rest) t).Note that in the last instance there is currently no way to signify that
aandtmust be different types, but when they are the sameOverlappingInstancescounts the instanceTypeFilter (t :* rest) tas more specific and chooses it over theTypeFilter (a :* rest) tone.