【问题标题】:Derive Ord with Quantified Constraints (forall a. Ord a => Ord (f a))使用量化约束导出 Ord (forall a. Ord a => Ord (f a))
【发布时间】:2020-05-01 17:36:15
【问题描述】:

有了量化的约束,我可以推导出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 proposals 0109-quantified-constraints。使用 ghc 8.6.5

【问题讨论】:

    标签: haskell typeclass derived-class quantified-constraints


    【解决方案1】:

    问题在于EqOrd 的超类,并且约束(forall a. Ord a =&gt; Ord (f a)) 不包含声明Ord (A f) 实例所需的超类约束Eq (A f)

    • 我们有(forall a. Ord a =&gt; Ord (f a))

    • 我们需要Eq (A f),即(forall a. Eq a =&gt; Eq (f a)),我们所拥有的并不暗示这一点。

    解决方案:将(forall a. Eq a =&gt; 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) =&gt; (Eq (f a), Ord (f a))) =&gt; Ord (A f) 如此亲密。你知道为什么会有差异吗?
    • 这也不意味着forall a. Eq a =&gt; Eq (f a)。 (从逻辑上看(A /\ B) =&gt; (C /\ D)并不暗示A =&gt; C
    • 其实你写的等价于forall a. Ord a =&gt; Ord (f a)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 2023-03-11
    • 1970-01-01
    相关资源
    最近更新 更多