匿名类型函数

时间:2013-10-06 15:13:37

标签: haskell anonymous-function data-kinds type-constructor

这是对上一个问题的跟进:Type-level Map with DataKinds,从收到的两个答案开始。

我的目标是获取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)

当我实际尝试使用几种类型时,我遇到了一个问题。 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

但当然,you can't partially apply type synonyms,肯定会有所作为。有没有(其他)方法来实现这个目标?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

aavogt的答案肯定完成了工作,但我发现了singletons library使用Data.Promotion的替代解决方案。此库已包含FlipMap$的类型系列以及其他大部分Prelude。

例如,

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

几乎直接来自this amazing answer