nobsun です。

> Main> foo (2,3)
> ERROR - Unresolved overloading
> *** Type       : (Num a, Num b, FooArg (b,a)) => Int
> *** Expression : foo (2,3)
> 
> むむむ。

あっとこれは、2 とか 3 が Int であることが推論できないからです。
この場合は明示的に Int であることを教えてやる必要があります。

Main> foo (2::Int,3::Int) 
5

多相関数の場合には、引数の型を特定できないと、実体を探せないので、
このようなことが起ります。2 と 3 は foo の定義のなかで、+ の引数と
なっていますので、この + の型によって、型付けされます。で、+ の型は

Main> :t (+)
(+) :: Num a => a -> a -> a

です。つまり、引数、返り値が同じ型で、それが、Num クラスのインスタンス
であるということなので、2 や 3 は Num クラスのインスタンスであること
しか推論できないというわけです。

多相関数ではない場合、

bar :: (Int, Int) -> Int
bar (x,y) = x + y 

明示的に bar :: (Int,Int) -> Int と宣言されているので、

Main> bar (2,3)
5

となります。つまり、この場合は、逆に 2、3 ともに Int であるという
型付けが行われます。

また、bar (2,3) の値は Int であることが決定しますから、

Main> foo (bar (2,3), bar (4,5))
14

となり、foo はちゃんと動作します。今度は、明示的型宣言なしで、baz を

baz (x,y) = x + y 

と定義してみると、

Main> baz (2,3)
5

ですが、

Main> foo (baz (2,3), baz (4,5))
ERROR - Unresolved overloading
*** Type       : (Num a, Num b, FooArg (b,a)) => Int
*** Expression : foo (baz (2,3),baz (4,5))

となります。理由は、baz の型にあります。

Main> :t baz
baz :: Num a => (a,a) -> a

baz の返す値は、Num クラスのインスタンスであることしかわからないからです。

--nobsun



--
ML: haskell-jp / quickml.com
使い方: http://QuickML.com/