Concurrent Clean : 型クラスとクラスコンテキスト

classに付けられたクラスコンテキストと、instanceに付けられたクラスコンテキストでは意味が違う。

class Measured a v | Monoid v where
  measure :: a -> v

という宣言は、単に、Measuredクラスに属する型は、Monoidクラスにも属していますということを言っているに過ぎない。そのため、

instance Measured Int v where
  measure _ = zero

と書こうとしても、zero関数がコンテキストで与えられていないために失敗する。

instance Measured Int v | Monoid v where
  measure _ = zero

と書かなければならない。(無駄な指定を行っているように見えるが、そういうルールである)
これは、instanceに付加されたクラスコンテキストは、

instance Measured Int v | Monoid v where
  measure :: Int -> v | Monoid v
  measure _ = zero

というように展開されて解釈されるのに対し、classに付加されたクラスコンテキストは、そのようには解釈されないためである。
この制限は、次のようなケースでより顕著となる。

class A a b where
  g :: a -> b
  h :: a -> b
instance A a Int | toInt a where
  g a = toInt a
  h a = g a

というように、h関数からg関数を呼び出そうとした場合、コンパイルエラーとなる。これは、h関数の型にAクラスのコンテキストが付加されていないため、g関数がコンテキストから取得できないためである。
ややこしい。