8 haskell overloading typeclass ghc
I'm researching how powerful function overloading in GHC is. I've written the following code:
class F_third_arg a where
run_f :: (Integer, a) -> Integer
instance F_third_arg Integer where
run_f (_, x) = x
instance F_third_arg String where
run_f (x, _) = x
my_fun :: (F_third_arg a) => Integer -> (a -> Integer)
my_fun x = \a -> run_f(x, a)
main :: IO ()
main = putStrLn $ show( ((my_fun::Integer->(Integer->Integer)) 5) $ 6)
Run Code Online (Sandbox Code Playgroud)
(yes, I need -XTypeSynonymInstances -XFlexibleInstances) and I was surprised that the compiler needs the type annotation near the call to my_fun. It is applied to two numbers -- what's the problem with infering this annotation? What are the rules of overloading with these two extensions turned on?
您的代码的问题是数字文字本身已经过载.所以文字6有类型Num a => a,而my_fun 5有类型F_third_arg b => b -> Integer.因此在类型推断期间,它统一了这两个类型变量.但由于没有其他要求,GHC无法在此处找到具体类型,并给出了相应的错误消息:
test.hs:16:26:
No instance for (F_third_arg a0) arising from a use of `my_fun'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance F_third_arg String -- Defined at test.hs:9:10
instance F_third_arg Integer -- Defined at test.hs:6:10
In the expression: (my_fun 5)
In the first argument of `show', namely `((my_fun 5) $ 6)'
In the second argument of `($)', namely `show ((my_fun 5) $ 6)'
test.hs:16:38:
No instance for (Num a0) arising from the literal `6'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Num Double -- Defined in `GHC.Float'
instance Num Float -- Defined in `GHC.Float'
instance Integral a => Num (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus three others
In the second argument of `($)', namely `6'
In the first argument of `show', namely `((my_fun 5) $ 6)'
In the second argument of `($)', namely `show ((my_fun 5) $ 6)'
人们可能期望编译器注意到Integer唯一满足这两个要求的类型,但是这种启发式方法会使您的代码相对脆弱,即它会因为您添加新实例(例如F_third_arg Double)而中断.因此,编译器会拒绝代码并要求您明确说明相关类型.
你找到了一种方法来修复它,但@ leftroundabouts的使用建议6::Integer有点好.