Ho un tipo di testimone per gli elenchi tipo di livello,È sempre sicuro usare unsafeCoerce per le uguaglianze valide?
data List xs where
Nil :: List '[]
Cons :: proxy x -> List xs -> List (x ': xs)
nonché le seguenti utilità.
-- 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
Ora, ho due definizioni diverse ma equivalenti di una funzione inversa tipo-livello,
-- 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]
Il primo è più efficiente, ma il secondo è più facile da usare quando dimostrando cose al compilatore , quindi sarebbe bello avere una prova di equivalenza. Per fare ciò, ho bisogno di una prova di Rev acc xs :~: Reverse' xs ++ acc
. Questo è ciò che mi si avvicinò con:
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)
Purtroppo, revAppend
è O (n³), che sconfigge completamente lo scopo di questo esercizio. Tuttavia, siamo in grado di bypassare tutto questo e ottenere O (1) utilizzando unsafeCoerce
:
revAppend :: Rev acc xs :~: Reverse' xs ++ acc
revAppend = unsafeCoerce Refl
Questa funzione è sicura? E il caso generale? Ad esempio, se ho due famiglie di tipi F :: k -> *
e G :: k -> *
e so che sono equivalenti, è sicuro definire quanto segue?
equal :: F a :~: G a
equal = unsafeCoerce Refl
Cosa sono 'Refl' e': ~: '? E 'forse il tuo testimone di tipo uguaglianza, qualcosa come 'data a: ~: b dove Refl :: a: ~: a'? – Cirdec
@Cirdec Esattamente. Puoi trovare la definizione in base (vedi [Data.Type.Equality] (http://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Type-Equality.html)) – YellPika
Sollevato direttamente da [Il blog di Richard Eisenberg] (https://typesandkinds.wordpress.com), se sai che le tue prove terminano e vuoi solo che GHC le scriva, puoi aggiungere '{- # RULES" revAppend "revAppend ... = unsafeCoerce Refl # -} '.Nessun sovraccarico di runtime e la verifica viene ancora verificata: solo la terminazione viene lasciata deselezionata. – Alec