Этот 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 не примет это напрямую.

Другие вопросы по тегам