2017-02-15 5 views
2

Je suis en train de remplir le trou dans l'extrait suivantcontraintes INFER à la fois si et bien de type égalité

import Data.Proxy 
import GHC.TypeLits 
import Data.Type.Equality 
import Data.Type.Bool 
import Unsafe.Coerce 

ifThenElse :: forall (a :: Nat) (b :: Nat) x l r. 
    (KnownNat a, KnownNat b, x ~ If (a==b) l r) => 
    Proxy a -> Proxy b -> Either (x :~: l) (x :~: r) 
ifThenElse pa pb = case sameNat pa pb of 
    Just Refl -> Left Refl 
    Nothing -> Right $ unsafeCoerce Refl -- This was the hole 

Est-il possible?

Modifier: Vérifié la source de sameNat et il s'avère qu'ils utilisent unsafeCoerce. J'ai modifié le code ci-dessus en conséquence.

+1

Vous devriez probablement poster votre modification comme réponse (et annuler l'édition). – Alec

+0

Le problème général semble être que, bien que la correspondance de modèle GADT fournisse des contraintes d'égalité, elle ne fournit jamais de contraintes d'inégalité, donc nous ne pouvons pas convaincre GHC que la première clause de la famille de type fermé n'est pas prise. Nous avons probablement besoin de plus de soutien de la part de GHC pour faire cela à l'avenir, AFAICS. – chi

+0

Ugh, vous pouvez dire simplement en regardant le type que cela ne va pas être facile à prouver, même avec un 'Nat' inductif (plutôt que celui cassé dans' GHC.TypeLits'). Comment as-tu réussi à te peindre dans ce coin? Nous pourrions être en mesure de vous conseiller sur la façon de refaire votre programme afin que vous n'ayez pas besoin de telles preuves. –

Répondre

2

Une solution possible consiste à utiliser la bibliothèque singletons pour obtenir des fonctions de niveau terme représentant les fonctions de niveau (ou vice versa).

L'essentiel de c'est:

import Data.Singletons.Prelude 

(...)

case (sing :: Sing a) %:== (sing :: Sing b) of 
    STrue -> Left Refl 
    SFalse -> Right Refl 

J'ai mis un self-contained file toutes les importations et les extensions de langage aussi.

+0

Merci beaucoup! Est-ce que '%: ==' n'est pas documenté? Je ne peux pas le trouver. – fakedrake

+1

'Data.Singletons.Prelude' réexporte' Data.Singletons.Prelude.Eq' où vous pouvez trouver ['(%: ==)'] (https://hackage.haskell.org/package/singletons-2.2 /docs/Data-Singletons-Prelude-Eq.html#v:-37-:-61--61-) – gallais