Haskellで引数の型を可変に

C++やら.Netやらでよくあるような同じ名称だけど異なる引数を持つ関数(正しい名称は忘れたけど)ってHaskellでできないんだろうかと思って調べた。
結論としては関数も型なのでできるのだが、FlexibleInstances拡張を入れる必要があるっぽい。
以下がすごい適当な例。

{-# LANGUAGE FlexibleInstances #-}

class TestFunc a where
    testFunc :: a

instance TestFunc Integer where
    testFunc = -1
instance TestFunc String where
    testFunc = "test!!"
instance TestFunc (() -> Integer) where
    testFunc a = -2
instance TestFunc (Integer -> Integer) where
    testFunc a = a + 1
instance TestFunc (Integer -> Integer -> Integer) where
    testFunc a b = a + b + 1
instance TestFunc ((Integer, Integer) -> Integer) where
    testFunc (a, b) = a + b - 1

ただ、これをやると、どのケースに該当するのか、型がなかなかうまく推論されてくれないので、ちょっと利便性は落ちる感じだなあ。
もっと便利に使う方法とかないのだろうか。

カリー化とか考えなくて、ある程度まで形が決まってるなら、以下みたいにやる方が型推論はうまく働いてくれるっぽい?

{-# LANGUAGE FlexibleInstances #-}

class TestF a where
    testF :: Integral b => a -> b

instance TestF Integer where
    testF a = fromIntegral $ a + 1
instance TestF Int where
    testF a = fromIntegral $ (toInteger a) + 1
 -- 以下だとUndecidableInstances拡張が必要。
 -- なんとなく理解はできるけどちょっと気持ち悪いなあ。
 -- instance (Integral a) => TestF (a) where
 --     testF a = fromIntegral $ (toInteger a) + 1
instance (Integral a, Integral b) => TestF (a, b) where
    testF (a, b) = fromIntegral $ (toInteger a) + (toInteger b) + 1
instance (Integral a, Integral b, Integral c) => TestF (a, b, c) where
    testF (a, b, c) = fromIntegral $ (toInteger a) + (toInteger b) + (toInteger c) + 1
instance TestF String where
    testF s = fromIntegral $ 0

いろいろ試してみると型推論が効いたり効かなかったりする。理解できるものもあるけど、理解しがたい結果もある。
うーむ。まだ理解が甘いってことだろうか。