2

これは、前の質問のフォローアップです: Type-level Map with DataKinds、受け取った2つの回答から始めます。

私の目標は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 への type-function " 引数は、HList要素の型を最後の引数として取り、新しい型を返す必要があります。これは時々うまくいきます:

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

しかし、test の定義でタプルの順序を入れ替えたい場合はどうすればよいでしょうか? 私の最初の試みは、型シノニムを定義することでした:

type RevIntTup b = (b,Int)

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

しかしもちろん、type synonyms を部分的に適用することはできません。これを達成する(他の)方法はありますか?

4

2 に答える 2

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
于 2013-10-06T22:12:59.513 に答える
1

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

これは、この驚くべき答えからほぼ直接得られます。

于 2014-06-05T13:17:44.233 に答える