haskell - GHC 扩展的语义允许对方法进行限制 (-XConstrainedClassMethods)

标签 haskell polymorphism ghc typeclass

以下引自 GHC 用户指南(Haskell Platform 2012.4.0.0)...

7.6.1.3. Class method types

Haskell 98 prohibits class method types to mention constraints on the class type variable, thus:

class Seq s a where
  fromList :: [a] -> s a
  elem     :: Eq a => a -> s a -> Bool

The type of elem is illegal in Haskell 98, because it contains the constraint Eq a, constrains only the class type variable (in this case a). GHC lifts this restriction (flag -XConstrainedClassMethods).



但是,我没有看到任何关于这意味着什么的解释。我可以看到两种可能性...
  • Seq类型类隐式获得 Eq a来自 elem 的约束.
  • elem方法不能用于类型类 Seqa 的情况下不是 Eq 类的成员(或者它是一个成员,但不知道在哪里使用 elem)。

  • 我强烈怀疑(2),因为它似乎可能有用, while(1) 似乎没用。 (2) 基本上允许为可以支持的情况定义方法,而不将类型类限制为仅针对这些情况进行实例化。

    这个例子似乎正是激发了这一点——这个想法是 elem对于序列来说通常是一个有用的操作,没有它就太有值(value)了,但我们也希望支持那些 elem 的序列。是不支持的,例如函数序列。

    我是对的,还是我错过了什么?这个扩展的语义是什么?

    最佳答案

    注意:好像是 there is a bug in GHC >= 7这使得 GHC 即使在 Haskell 98 模式下也接受约束类方法。

    此外,手册中的示例总是在 MultiParamTypeClasses 时被接受。已启用,无论 ConstrainedMethodTypes 是否扩展已打开(也可能是一个错误)。

    类型为elem :

    elem     :: Eq a => a -> s a -> Bool
    
    as是类类型变量,Eq a是对类类型变量 a 的约束.正如手册所说,Haskell 98 禁止此类约束(FWIW,它也禁止多参数类型类)。因此,在 Haskell 98 模式下不应接受以下代码(我认为在 Haskell 2010 中也禁止使用):
    class Compare a where
      comp :: Eq a => a -> a -> Bool
    

    事实上,GHC 6.12.1 拒绝了它:
    Prelude> :load Test.hs
    [1 of 1] Compiling Main             ( Test.hs, interpreted )
    
    Test.hs:3:0:
        All of the type variables in the constraint `Eq a'
        are already in scope (at least one must be universally quantified here)
            (Use -XFlexibleContexts to lift this restriction)
        When checking the class method: comp :: (Eq a) => a -> a -> Bool
        In the class declaration for `Compare'
    Failed, modules loaded: none.
    Prelude> :set -XConstrainedClassMethods
    Prelude> :load Test.hs
    [1 of 1] Compiling Main             ( Test.hs, interpreted )
    Ok, modules loaded: Main.
    

    这个想法是应该使用父类(super class)约束:
    class (Eq a) => Compare a where
      comp :: a -> a -> Bool
    

    关于语义,您可以使用以下代码轻松检查类方法约束是否隐式添加父类(super class)约束:
    {-# LANGUAGE ConstrainedClassMethods #-}
    module Main where
    
    class Compare a where
      comp :: (Eq a) => a -> a -> Bool
      someMethod :: a -> a -> a
    
    data A = A deriving Show
    data B = B deriving (Show,Eq)
    
    instance Compare A where
      comp = undefined
      someMethod A A = A
    
    instance Compare B where
      comp = (==)
      someMethod B B = B
    

    使用 GHC 6.12.1 进行测试:
    *Main> :load Test.hs
    [1 of 1] Compiling Main             ( Test.hs, interpreted )
    Ok, modules loaded: Main.
    *Main> comp A
    
    <interactive>:1:0:
        No instance for (Eq A)
          arising from a use of `comp' at <interactive>:1:0-5
        Possible fix: add an instance declaration for (Eq A)
        In the expression: comp A
        In the definition of `it': it = comp A
    *Main> someMethod A A
    A
    *Main> comp B B
    True
    

    答案:不,它没有。约束仅适用于具有约束类型的方法。所以你是对的,这是可能性 #2。

    关于haskell - GHC 扩展的语义允许对方法进行限制 (-XConstrainedClassMethods),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16139454/

    相关文章:

    haskell - IO monad 处理,简化绑定(bind)语法

    haskell - fmap 应用于类型变量以外的类型

    haskell - 新类型派生 Monad 错误

    c - 在 Haskell 中键入 : Passing a number that looks fractional, 但始终是整数(类型别名)

    performance - 与斐波那契微基准测试中的 C 相比提高 Haskell 的性能

    c++ - 如何检查继承类的指针?

    c# - 如何强制派生类填充基类中定义的列表?

    c++ - C++ 17中的泛型工厂机制

    haskell - 函数依赖和重叠实例

    haskell - 在删除不透明的 FFI 对象之前,垃圾回收需要多长时间?有可能以某种方式加快速度吗?