Вивести Ord з кількісно обмеженими обмеженнями (для a. Ord a => Ord (fa))


10

З кількісно вираженими обмеженнями я можу вийти Eq (A f)просто добре? Однак, коли я намагаюся отримати Ord (A f), це не вдається. Я не розумію, як використовувати кількісні обмеження, коли клас обмеження має надклас. Як вивести Ord (A f)та інші класи, які мають суперкласи?

> 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. Я також вивчив пропозиції ghc 0109-кількісно обмежені . Використання ghc 8.6.5

Відповіді:


8

Проблема полягає в тому, що Eqце суперклас Ord, і обмеження (forall a. Ord a => Ord (f a))не тягне за собою обмеження надкласового класу Eq (A f), необхідне для оголошення Ord (A f)примірника.

  • Ми маємо (forall a. Ord a => Ord (f a))

  • Нам потрібно Eq (A f), тобто, (forall a. Eq a => Eq (f a))що не має на увазі те, що ми маємо.

Рішення: додайте (forall a. Eq a => Eq (f a))до Ordекземпляра.

(Я насправді не розумію, як повідомлення про помилку, яке надає GHC, стосується проблеми.)

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

Або трохи охайніше:

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

Я був так близько з deriving instance (forall a. (Eq a, Ord a) => (Eq (f a), Ord (f a))) => Ord (A f). Чи знаєте ви, чому є різниця?
Вільям Раснак

1
Це також не означає forall a. Eq a => Eq (f a). (розглядається з точки зору логіки (A /\ B) => (C /\ D)не означає A => C)
Лі-яо Ся

1
Насправді те, що ви написали, рівнозначне forall a. Ord a => Ord (f a).
Лі-яо Ся

Дякую за пояснення!
Вільям Раснак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.