Функции анонимного типа

Это продолжение предыдущего вопроса: Карта на уровне типов с типами данных, начиная с из двух полученных ответов.

Моя цель — взять HList произвольных типов и превратить их в список связанных/производных типов.

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)

Когда я на самом деле попытался сделать это с несколькими типами, я столкнулся с проблемой. Аргумент type-function " для TypeMap должен принимать тип элемента HList в качестве последнего аргумента и возвращать новый тип. Иногда это работает нормально:

test :: HList rqs -> HList (TypeMap ((,) Int) rqs)
test HNil = HNil
test (HCons x xs) = HCons (3,x) $ test xs

Но что, если я хочу изменить порядок кортежа в определении теста? Моей первой попыткой было определить синоним типа:

type RevIntTup b = (b,Int)

test2 :: HList rqs -> HList (TypeMap RevIntTup rqs)
test2 HNil = HNil
test2 (HCons x xs) = HCons (x,3) $ test2 xs

Но, конечно, вы не можете частично введите синонимы, что, безусловно, поможет. Есть ли (другой) способ добиться этого?


person crockeea    schedule 06.10.2013    source источник


Ответы (2)


Вы должны быть в состоянии написать FlipTypeMap... но это не очень удобно. Здесь может быть лучшим выбором сделать версию уровня типа map ($ 2) (map (/) [1,2,3]) вместо map (flip (/) 2) [1,2,3], воспользовавшись преимуществами -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
person aavogt    schedule 06.10.2013

Ответ aavogt, безусловно, выполнил свою работу, но я обнаружил альтернативное решение с использованием Data.Promotion из библиотеки синглтонов . Эта библиотека уже включает в себя семейства шрифтов для Flip, Map, $ и большей части остальной части Prelude.

Например,

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

который исходит почти непосредственно из этот удивительный ответ.

person crockeea    schedule 05.06.2014