Этот GADT на самом деле имеет тип ролевой репрезентативной
Этот тип данных может иметь type role HCons' representational representational
, что позволяет использовать coerce
добавлять или удалять новые типы, применяемые к элементам, без необходимости обхода списка.
data HNil' = HNil'
data HCons' a b = HCons' a b
Однако синтаксис этих списков не такой хороший, как у следующих GADT.
data HList (l::[*]) where
HNil :: HList '[]
HCons :: e -> HList l -> HList (e ': l)
У меня есть класс для преобразования между этими двумя представлениями, так что Prime (HList [a,b]) ~ HCons' a (HCons' b HNil')
, Этот класс делает
coerceHList :: Coercible (Prime a) (Prime b) => HList a -> HList b
coerceHList = unsafeCoerce
безопасный?
1 ответ
Я не думаю, что само существование конверсии достаточно. Например, следующее также позволяет мне преобразовывать между GADT и принудительной парой типов, но, конечно, было бы небезопасно напрямую приводить GADT:
newtype Age = Age Int
data Foo a where
I :: Bool -> Int -> Foo Int
A :: Age -> Bool -> Foo Age
class ConvFoo a where
toFoo :: (Bool, a) -> Foo a
fromFoo :: Foo a -> (Bool, a)
instance ConvFoo Int where
toFoo (b, i) = I b i
fromFoo (I b i) = (b, i)
instance ConvFoo Age where
toFoo (b, a) = A a b
fromFoo (A a b) = (b, a)
Я также мог бы тривиально определить UnFoo
функция типа похожа на Prime
,
Я думаю, что ключевое отличие между этими двумя примерами в том, что в моем, Age
а также Int
имеют такое же представление, в то время как в вашем '[]
а также e':l
не имеют того же представления.
Таким образом, все еще есть смысл сказать, как вы предлагаете в названии, что l
имеет репрезентативную роль типа, потому что очевидно, что HList l1
а также HList l2
имеют одинаковые представления, если l1
а также l2
имеют одинаковые представления.
Однако, поскольку в теории представления зависят от реализации, я не думаю, что вы когда-либо сможете считать это абсолютно безопасным, пока GHC не примет это напрямую.