我有型層級清單證人類型,使用unsafeCoerce進行有效平等總是安全的嗎?
data List xs where
Nil :: List '[]
Cons :: proxy x -> List xs -> List (x ': xs)
以及以下實用程序。現在
-- Type level append
type family xs ++ ys where
'[] ++ ys = ys
(x ': xs) ++ ys = x ': (xs ++ ys)
-- Value level append
append :: List xs -> List ys -> List (xs ++ ys)
append Nil ys = ys
append (Cons x xs) ys = Cons x (append xs ys)
-- Proof of associativity of (++)
assoc :: List xs -> proxy ys -> proxy' zs -> ((xs ++ ys) ++ zs) :~: (xs ++ (ys ++ zs))
assoc Nil _ _ = Refl
assoc (Cons _ xs) ys zs = case assoc xs ys zs of Refl -> Refl
,我有一個類型級反轉函數的兩個不同但等價的定義,
-- The first version, O(n)
type Reverse xs = Rev '[] xs
type family Rev acc xs where
Rev acc '[] = acc
Rev acc (x ': xs) = Rev (x ': acc) xs
-- The second version, O(n²)
type family Reverse' xs where
Reverse' '[] = '[]
Reverse' (x ': xs) = Reverse' xs ++ '[x]
首先是更有效的,但第二個是更容易證明東西到編譯器時使用,所以有一個等價的證明是很好的。爲了做到這一點,我需要Rev acc xs :~: Reverse' xs ++ acc
的證明。這是我想出了:
revAppend :: List acc -> List xs -> Rev acc xs :~: Reverse' xs ++ acc
revAppend _ Nil = Refl
revAppend acc (Cons x xs) =
case (revAppend (Cons x acc) xs, assoc (reverse' xs) (Cons x Nil) acc) of
(Refl, Refl) -> Refl
reverse' :: List xs -> List (Reverse' xs)
reverse' Nil = Nil
reverse' (Cons x xs) = append (reverse' xs) (Cons x Nil)
不幸的是,revAppend
是O(N 3),這完全違背了這項工作的目的。但是,我們可以繞過這一切,通過使用unsafeCoerce
得到O(1):
revAppend :: Rev acc xs :~: Reverse' xs ++ acc
revAppend = unsafeCoerce Refl
這安全嗎?一般情況如何?例如,如果我有兩個類型系列F :: k -> *
和G :: k -> *
,並且我知道它們是等價的,那麼定義以下內容是否安全?
equal :: F a :~: G a
equal = unsafeCoerce Refl
什麼是'Refl'和':〜:'?這可能是你類型平等的見證,例如'data a:〜:b where Refl :: a:〜:a'? – Cirdec 2014-11-01 06:25:54
@Cirdec正確。你可以在base中找到定義(參見[Data.Type.Equality](http://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Type-Equality.html)) – YellPika 2014-11-01 06:34:29
直接從[Richard Eisenberg的博客](https://typesandkinds.wordpress.com),如果你知道你的證明終止了,只希望GHC輸入檢查他們,你可以添加'{ - #RULES'revAppend「revAppend ... = unsafeCoerce Refl # - }'。沒有運行時間的開銷,你的證明仍然被檢查 - 只有終止不被選中。 – Alec 2017-02-23 00:48:20