Deriva Ord con vincoli quantificati (forall a. Ord a => Ord (fa))


10

Con vincoli quantificati posso derivare Eq (A f)bene? Tuttavia, quando provo a derivare Ord (A f), fallisce. Non capisco come usare vincoli quantificati quando la classe di vincolo ha una superclasse. Come posso derivare Ord (A f)e altre classi che hanno superclassi?

> 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. Ho anche esaminato le proposte ghc 0109-quantificate-vincoli . Usare ghc 8.6.5

Risposte:


8

Il problema è che si Eqtratta di una superclasse Orde il vincolo (forall a. Ord a => Ord (f a))non comporta il vincolo di superclasse Eq (A f)richiesto per dichiarare Ord (A f)un'istanza.

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

  • Abbiamo bisogno Eq (A f), cioè, (forall a. Eq a => Eq (f a))che non è implicito da ciò che abbiamo.

Soluzione: aggiungere (forall a. Eq a => Eq (f a))alla Ordistanza.

(In realtà non capisco come il messaggio di errore fornito da GHC sia correlato al 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)

O un po 'più in ordine:

{-# 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)

Ero così vicino deriving instance (forall a. (Eq a, Ord a) => (Eq (f a), Ord (f a))) => Ord (A f). Sai perché c'è una differenza?
William Rusnack, il

1
Ciò non implica forall a. Eq a => Eq (f a)neanche. (visto in termini logici (A /\ B) => (C /\ D)non implica A => C)
Li-yao Xia

1
In effetti ciò che hai scritto equivale a forall a. Ord a => Ord (f a).
Li-yao Xia

Grazie per la spiegazione!
William Rusnack, il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.