Search code examples
haskellanonymous-functiondata-kindstype-constructor

Anonymous Type Functions


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?


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