6

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

7.6.1.3。类方法类型

Haskell 98 禁止类方法类型提及对类类型变量的约束,因此:

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

elem 的类型在 Haskell 98 中是非法的,因为它包含约束 Eq a,仅约束类类型变量(在本例中为 a)。GHC 解除了这个限制(标志 -XConstrainedClassMethods)。

但是,我没有看到任何关于这意味着什么的解释。我可以看到两种可能性...

  1. Seq类型类隐式地从中获得Eq a约束elem
  2. 在不是类成员的情况下(或者它是成员,但不知道在哪里使用) ,该elem方法不能用于类型类。SeqaEqelem

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

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

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

4

1 回答 1

7

注意:似乎GHC >= 7 中存在一个错误,即使在 Haskell 98 模式下,GHC 也可以接受受约束的类方法。

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.

这个想法是应该使用超类约束:

class (Eq a) => Compare a where
  comp :: a -> a -> Bool

关于语义,您可以使用以下代码轻松检查类方法约束是否隐式添加超类约束:

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

于 2013-04-22T05:51:28.613 回答