This is a followup to a previous question: Type-level Map with DataKinds, starting with from the two answers it received.
My goal is to take a HList
of arbitrary types and turn it into a list of related/derived types
type family TypeMap (a :: * -> *) (xs :: [*]) :: [*]
type instance TypeMap t '[] = '[]
type instance TypeMap t (x ': xs) = t x ': TypeMap t xs
data HList :: [*] -> * where
HNil :: HList '[]
HCons :: a -> HList as -> HList (a ': as)
When I actually tried to do this with a few types, I ran into a problem. The type-function " argument to TypeMap has to take the HList
element type as its last argument and return a new type. This works okay sometimes:
test :: HList rqs -> HList (TypeMap ((,) Int) rqs)
test HNil = HNil
test (HCons x xs) = HCons (3,x) $ test xs
But what if I wanted to switch the order of the tuple in the definition of test? My first attempt was to define a type synonym:
type RevIntTup b = (b,Int)
test2 :: HList rqs -> HList (TypeMap RevIntTup rqs)
test2 HNil = HNil
test2 (HCons x xs) = HCons (x,3) $ test2 xs
But of course, you can't partially apply type synonyms, which would certainly do the trick. Is there any (other) way to achieve this?
You should be able to write a FlipTypeMap
... but that's not very composable. A better choice here might be to do the type-level version of map ($ 2) (map (/) [1,2,3])
instead of map (flip (/) 2) [1,2,3]
by taking advantage of -XPolyKinds
:
type family TypeMap (a :: j -> k) (xs :: [j]) :: [k]
type instance TypeMap t '[] = '[]
type instance TypeMap t (x ': xs) = t x ': TypeMap t xs
type family ApList (xs :: [j -> k]) (a :: j) :: [k]
type instance ApList '[] t = '[]
type instance ApList (x ': xs) t = x t ': ApList xs t
test2 :: HList rqs -> HList (TypeMap (,) rqs `ApList` Int)
test2 HNil = HNil
test2 (HCons x xs) = HCons (x,3) $ test2 xs