문제

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

다른 팁

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top