8

Y at-il une connexion implémentée entre propositional et promoted égalité?Y a-t-il un lien entre `a: ~: b` et` (a: == b): ~: True`?

Disons que je

prf :: x :~: y 

portée pour certains Symbol s; par modèle correspondant à ce sujet étant Refl, je peux transformer cela en

prf' :: (x :== y) :~: True 

comme ceci:

fromProp :: (KnownSymbol x, KnownSymbol y) => x :~: y -> (x :== y) :~: True 
fromProp Refl = Refl 

Mais qu'en l'autre sens? Si je tente

toProp :: (KnownSymbol x, KnownSymbol y) => (x :== y) :~: True -> x :~: y 
toProp Refl = Refl 

alors tout ce que je reçois est

• Could not deduce: x ~ y 
    from the context: 'True ~ (x :== y) 
+1

Bien sûr, 'toProp _ = unsafeCoerce Refl'. 'sameSymbol' est défini de cette façon, donc je doute que vous puissiez faire mieux. – user3237465

+1

Vous pouvez également écrire 'toProp Refl = fromJust $ sameSymbol (Proxy :: Proxy x) (Proxy :: Proxy y)' mais cela n'est que légèrement meilleur que d'utiliser 'unsafeCoerce'. – user2407038

Répondre

8

Oui, aller entre les deux représentations est possible (en supposant la mise en œuvre de :== est correct), mais il nécessite le calcul.

Les informations dont vous avez besoin ne sont pas présentes dans le booléen lui-même (it's been erased to a single bit); vous devez le récupérer. Cela implique d'interroger les deux participants du test d'égalité booléen original (ce qui signifie que vous devez les garder à l'exécution), et d'utiliser votre connaissance du résultat pour éliminer les cas impossibles. Il est plutôt fastidieux de refaire un calcul pour lequel vous connaissez déjà la réponse!

Travailler en Agda, et à l'aide Naturals au lieu de cordes (parce qu'ils sont plus simples):

open import Data.Nat 
open import Relation.Binary.PropositionalEquality 
open import Data.Bool 

_==_ : ℕ -> ℕ -> Bool 
zero == zero = true 
suc n == suc m = n == m 
_ == _ = false 

==-refl : forall n -> (n == n) ≡ true 
==-refl zero = refl 
==-refl (suc n) = ==-refl n 


fromProp : forall {n m} -> n ≡ m -> (n == m) ≡ true 
fromProp {n} refl = ==-refl n 

-- we have ways of making you talk 
toProp : forall {n m} -> (n == m) ≡ true -> n ≡ m 
toProp {zero} {zero} refl = refl 
toProp {zero} {suc m}() 
toProp {suc n} {zero}() 
toProp {suc n} {suc m} p = cong suc (toProp {n}{m} p) 

En principe, je pense que vous pourriez faire ce travail en Haskell utilisant singletons, mais pourquoi pris la peine? N'utilisez pas de booléens!

+1

C'est la bonne réponse, mais je crains que ce ne soit pas faisable chez Haskell pour le moment. Dans Haskell 'n, m' ne peut pas être éliminé car ils ont un type opaque-ish' Symbol'. Nous pouvons nous baser sur l'instance de 'KnownSymbol n', mais cela ne permet que de récupérer le nom du symbole sous forme de chaîne au niveau de la valeur, ce qui n'aide pas. – chi

+1

@chi Oui, c'est ce que j'essayais d'obtenir quand j'ai dit "vous devez avoir les valeurs à l'exécution". Le type spécifié dans la question n'est pas satisfaisant dans Haskell, vous auriez besoin de paramètres de type 'Sing x' et' Sing y'. –

+0

@BenjaminHodgson: mais même si j'avais les paramètres 'Sing x' et' Sing y', je ne suis pas sûr (pour 'Symbol's) que je puisse me les récurser. – Cactus