Dériver Ord avec des contraintes quantifiées (pour tout a. Ord a => Ord (fa))

10

Avec des contraintes quantifiées, je peux dériver Eq (A f)très bien? Cependant, lorsque j'essaie de dériver Ord (A f), cela échoue. Je ne comprends pas comment utiliser des contraintes quantifiées lorsque la classe de contraintes a une superclasse. Comment puis-je dériver Ord (A f)et d'autres classes qui ont des superclasses?

> newtype A f = A (f Int)
> deriving instance (forall a. Eq a => Eq (f a)) => Eq (A f)
> deriving instance (forall a. Ord a => Ord (f a)) => Ord (A f)
<interactive>:3:1: error:
     Could not deduce (Ord a)
        arising from the superclasses of an instance declaration
      from the context: forall a. Ord a => Ord (f a)
        bound by the instance declaration at <interactive>:3:1-61
      or from: Eq a bound by a quantified context at <interactive>:1:1
      Possible fix: add (Ord a) to the context of a quantified context
     In the instance declaration for 'Ord (A f)'

PS. J'ai également examiné les propositions ghc 0109-quantified-contraintes . Utilisation de ghc 8.6.5

William Rusnack
la source

Réponses:

8

Le problème est qu'il Eqs'agit d'une superclasse de Ord, et la contrainte (forall a. Ord a => Ord (f a))n'implique pas la contrainte de superclasse Eq (A f)qui est requise pour déclarer une Ord (A f)instance.

  • On a (forall a. Ord a => Ord (f a))

  • Nous avons besoin Eq (A f), c'est-à-dire, (forall a. Eq a => Eq (f a))ce qui n'est pas impliqué par ce que nous avons.

Solution: ajoutez (forall a. Eq a => Eq (f a))à l' Ordinstance.

(Je ne comprends pas vraiment comment le message d'erreur donné par GHC est lié au problème.)

{-# LANGUAGE QuantifiedConstraints, StandaloneDeriving, UndecidableInstances, FlexibleContexts #-}

newtype A f = A (f Int)
deriving instance (forall a. Eq a => Eq (f a)) => Eq (A f)
deriving instance (forall a. Eq a => Eq (f a), forall a. Ord a => Ord (f a)) => Ord (A f)

Ou un peu plus soigneusement:

{-# LANGUAGE ConstraintKinds, RankNTypes, KindSignatures, QuantifiedConstraints, StandaloneDeriving, UndecidableInstances, FlexibleContexts #-}

import Data.Kind (Constraint)

type Eq1 f = (forall a. Eq a => Eq (f a) :: Constraint)
type Ord1 f = (forall a. Ord a => Ord (f a) :: Constraint)  -- I also wanted to put Eq1 in here but was getting some impredicativity errors...

-----

newtype A f = A (f Int)
deriving instance Eq1 f => Eq (A f)
deriving instance (Eq1 f, Ord1 f) => Ord (A f)
Li-yao Xia
la source
J'étais si proche avec deriving instance (forall a. (Eq a, Ord a) => (Eq (f a), Ord (f a))) => Ord (A f). Savez-vous pourquoi il y a une différence?
William Rusnack
1
Cela n'implique pas non forall a. Eq a => Eq (f a)plus. (vu en termes de logique (A /\ B) => (C /\ D)n'implique pas A => C)
Li-yao Xia
1
En fait, ce que vous avez écrit équivaut à forall a. Ord a => Ord (f a).
Li-yao Xia
Merci pour l'explication!
William Rusnack