此数据类型可以具有type role HCons' representational representational,允许使用coerce添加或删除应用于元素的新类型,而无需遍历列表.
data HNil' = HNil'
data HCons' a b = HCons' a b
Run Code Online (Sandbox Code Playgroud)
但是,这些列表的语法不如具有以下GADT的语法好
data HList (l::[*]) where
HNil :: HList '[]
HCons :: e -> HList l -> HList (e ': l)
Run Code Online (Sandbox Code Playgroud)
我有一个类在这两个表示之间进行转换,这样Prime (HList [a,b]) ~ HCons' a (HCons' b HNil').该课程是否成功?
coerceHList :: Coercible (Prime a) (Prime b) => HList a -> HList b
coerceHList = unsafeCoerce
Run Code Online (Sandbox Code Playgroud)
安全?
我认为转换本身的存在还不够。例如,以下代码还允许我在 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)
Run Code Online (Sandbox Code Playgroud)
我还可以简单地定义一个UnFoo类似于 的类型函数Prime。
我认为这两个示例之间的主要区别在于,在我的Age和Int中确实具有相同的表示,而在您的'[]和中e':l没有相同的表示。
因此,正如您在标题中所建议的那样,仍然有理由说l具有角色代表性类型,因为很明显,如果HList l1和HList l2具有相同的表示,则l1和l2具有相同的表示。
然而,由于理论上表示是依赖于实现的,所以我认为在 GHC 直接接受它之前你不能认为这是绝对安全的。