... is a rigid type variable bound by ...

なんでこれがエラーになるのかわからないのは、まだなにか理解出来ていことがあるってことなんだろうな。

class Foo a where
    foobar :: (Bar b) => a -> b

class Bar a

newtype AFoo = MakeAFoo {foo_value :: Int}
newtype ABar = MakeABar {bar_value :: Int}

instance Foo AFoo where
    foobar x = MakeABar $ foo_value x

instance Bar ABar
    Couldn't match expected type `b' against inferred type `ABar'
      `b' is a rigid type variable bound by
          the type signature for `foobar' at tmp.hs:6:19
    In the expression: MakeABar $ foo_value x
    In the definition of `foobar': foobar x = MakeABar $ foo_value x
    In the definition for method `foobar'

ああ、なるほど。「(Bar b) => 」は「bがBarのインスタンスの *いずれか* である」という意味ではなく「Barのインスタンスである *任意の* bである」という意味になるので、具体的なBarのインスタンスABarを返してはいけない。なぜなら別のBarのインスタンスAnotherBarしかとらない関数にfoobarの返り値を渡すことが型推論上はvalidなのに、実行時に型が違ってエラーが起きてしまう。

class Foo a where
    foobar :: (Num b) => a -> b

newtype AFoo = MakeAFoo {foo_value :: Int}

instance Foo AFoo where
    foobar x = 1

これはOK。なんで?ああ、リテラルの1の型が(Num a) => aなのか?

class Foo a where
    foobar :: (Show b) => a -> b

newtype AFoo = MakeAFoo {foo_value :: Int}

instance Foo AFoo where
    foobar x = "1"

これは期待通りrigid type variableのエラーになる


で、どうやって解決するんだ?