Derivar Ord com restrições quantificadas (em geral a. Ord a => Ord (fa))

10

Com restrições quantificadas, posso derivar Eq (A f)muito bem? No entanto, quando tento derivar Ord (A f), ele falha. Eu não entendo como usar restrições quantificadas quando a classe de restrição tem uma superclasse. Como derivar Ord (A f)e outras classes que têm 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. Também examinei as propostas 0109-quantified-constraints do ghc . Usando o ghc 8.6.5

William Rusnack
fonte

Respostas:

8

O problema é que Eqé uma superclasse de Ord, e a restrição (forall a. Ord a => Ord (f a))não implica a restrição de superclasse Eq (A f)necessária para declarar uma Ord (A f)instância.

  • Nós temos (forall a. Ord a => Ord (f a))

  • Precisamos Eq (A f), isto é, o (forall a. Eq a => Eq (f a))que não está implícito no que temos.

Solução: adicione (forall a. Eq a => Eq (f a))à Ordinstância.

(Na verdade, não entendo como a mensagem de erro dada pelo GHC está relacionada ao problema.)

{-# 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 um pouco mais arrumado:

{-# 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
fonte
Eu estava tão perto deriving instance (forall a. (Eq a, Ord a) => (Eq (f a), Ord (f a))) => Ord (A f). Você sabe por que há uma diferença?
William Rusnack 15/01
11
Isso também não implica forall a. Eq a => Eq (f a). (visto em termos de lógica (A /\ B) => (C /\ D)não implica A => C)
Li-yao Xia 15/01
11
De fato, o que você escreveu é equivalente forall a. Ord a => Ord (f a).
Li-yao Xia 15/01
Obrigada pelo esclarecimento!
William Rusnack 15/01