2014-06-14 2 views
13

Этот тип данных может содержать type role HCons' representational representational, что позволяет использовать coerce для добавления или удаления новых типов, применяемых к элементам, без необходимости перебирать список.делает это GADT действительно имеющим представление роли типа

data HNil' = HNil' 
data HCons' a b = HCons' a b 

Однако синтаксис для этих списков не так хорошо, как те, со следующим GADT

data HList (l::[*]) where 
    HNil :: HList '[] 
    HCons :: e -> HList l -> HList (e ': l) 

У меня есть класс для convert between these two representations, так что Prime (HList [a,b]) ~ HCons' a (HCons' b HNil'). Делает этот класс

coerceHList :: Coercible (Prime a) (Prime b) => HList a -> HList b 
coerceHList = unsafeCoerce 

сейф?

+0

FWIW, да, я так думаю. Но я не знаю достаточно о внутренних ролях, чтобы на самом деле сделать убедительный аргумент. Ваш пример, похоже, является другим случаем, когда текущая система ролей недостаточно выразительна. – kosmikus

ответ

2

Я не думаю, что существование преобразования само по себе достаточно. Например, следующий также позволяет мне конвертировать между 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 не примет его напрямую.

+0

Я не уверен в «очевидном, что HList l1 и HList l2 имеют одинаковые представления, если l1 и l2 имеют одинаковые представления». Мы могли бы написать «HCons :: (el ~ (e ': l)) => e -> HList l -> HList el'. Тогда возможно, что ghc хранит что-то для 'el ~ (e ': l)', который ссылается на исходные типы 'e, el, l', а не те, которые в настоящее время находятся в конструкторе? – aavogt

+0

Даже тогда все «HCons» будут по-прежнему иметь такое же поверхностное представление, как и все остальные «HCons», не так ли? Поэтому, если 'e' и' HList l' также имели одинаковые представления, тогда все «HCons» будут. –

+0

Я думаю, что ключевым моментом является то, что '': 'и' '[] 'являются конкретными типами, которые должны быть разными, поэтому нет никакого риска запутать« HCons »и« HNil ». Я совсем не уверен, как правильно сформулировать это условие! –

Смежные вопросы