注: 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 です。