Why is annotation needed for this type in Haskell?

I will explore how powerful function overloading is in the GHC. I wrote 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) 

(yes, I need -XTypeSynonymInstances -XFlexibleInstances), and I was surprised that the compiler needed an annotation of the type next to my_fun . It applies to two numbers - what is the problem with the output of this annotation? What are the overload rules with these two extensions?

+8
overloading haskell ghc typeclass
source share
1 answer

The problem with your code is that the number literals themselves are already overloaded. Thus, letter 6 is of type Num a => a , and my_fun 5 is of type F_third_arg b => b -> Integer . Thus, during type inference, it combines these two type variables. But since they have no other requirements, the GHC cannot find a specific type to use here and gives the corresponding error message:

 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)'

One would expect the compiler to notice that Integer is the only type that fulfills both requirements, but such heuristics will make your code relatively fragile, i.e. it will break only because you add a new instance (e.g. F_third_arg Double ), therefore the compiler rejects the code and asks you to be explicit about the type in question.

You found one way to fix this, but the @leftroundaboutss suggestion of using 6::Integer bit nicer.

+7
source share

All Articles