Turunkan Ord dengan Batasan yang Dihitung (forall a. Ord a => Ord (fa))

10

Dengan batasan kuantitatif saya dapat memperoleh dengan Eq (A f)baik? Namun, ketika saya mencoba untuk menurunkan Ord (A f) gagal. Saya tidak mengerti bagaimana menggunakan batasan terkuantifikasi ketika kelas kendala memiliki superclass. Bagaimana cara mendapatkan Ord (A f)dan kelas lain yang memiliki kacamata super?

> 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. Saya juga telah memeriksa proposal ghc 0109-terkuantifikasi-kendala . Menggunakan ghc 8.6.5

William Rusnack
sumber

Jawaban:

8

Masalahnya adalah bahwa itu Eqadalah superclass Ord, dan batasannya (forall a. Ord a => Ord (f a))tidak memerlukan superclass constraint Eq (A f)yang diperlukan untuk mendeklarasikan Ord (A f)instance.

  • Kita punya (forall a. Ord a => Ord (f a))

  • Kita membutuhkan Eq (A f), yaitu, (forall a. Eq a => Eq (f a))yang tidak tersirat oleh apa yang kita miliki.

Solusi: tambahkan (forall a. Eq a => Eq (f a))ke Ordinstance.

(Saya sebenarnya tidak mengerti bagaimana pesan kesalahan yang diberikan oleh GHC berhubungan dengan masalah tersebut.)

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

Atau sedikit lebih rapi:

{-# 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
sumber
Aku sangat dekat dengannya deriving instance (forall a. (Eq a, Ord a) => (Eq (f a), Ord (f a))) => Ord (A f). Tahukah Anda mengapa ada perbedaan?
William Rusnack
1
Itu juga tidak menyiratkan forall a. Eq a => Eq (f a). (Dilihat dari segi logika (A /\ B) => (C /\ D)tidak menyiratkan A => C)
Li-yao Xia
1
Sebenarnya apa yang Anda tulis setara dengan forall a. Ord a => Ord (f a).
Li-yao Xia
Terima kasih untuk penjelasannya!
William Rusnack