Question

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?

Était-ce utile?

La solution

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

Autres conseils

aavogt's answer certainly got the job done, but I discovered an alternate solution using Data.Promotion from the singletons library. This library already includes type families for Flip, Map, $, and much of the rest of the Prelude.

For example,

test2 :: HList rqs -> HList (Map (FlipSym1 (TyCon2 (,)) $ Int) rqs)
test2 HNil = HNil
test2 (HCons x xs) = HCons (x,3) $ test2 xs

which is comes almost directly from this amazing answer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top