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)。

ただし、これが何を意味するのかについての説明はありません。2つの可能性が見えます...

  1. 型クラスはSeq暗黙的にEq aから制約を取得しますelem
  2. がクラスのメンバーではない場合(またはメンバーであるが、どこで使用されるか不明な場合) にはelem、型クラスに対してメソッドを使用することはできません。SeqaEqelem

(1) は役に立たないように見えるのに対し、(2) は潜在的に役立つと思われるので、私は強く疑っています。(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 に答える