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