注意:似乎GHC >= 7 中存在一个错误,即使在 Haskell 98 模式下,GHC 也可以接受受约束的类方法。
MultiParamTypeClasses
此外,无论ConstrainedMethodTypes
扩展是否打开(也可能是错误) ,启用时始终接受手册中的示例。
在类型elem
:
elem :: Eq a => a -> s a -> Bool
a
和s
是类类型变量,并且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。