Получите 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).
Ли Яо Ся
Спасибо за объяснение!
Уильям Руснак