Reputation: 34099
I have the following code snippet, that does not compile:
{-# LANGUAGE OverloadedStrings, TypeFamilies, MultiParamTypeClasses #-}
module Main where
class Add a b where
type SumTy a b
plus :: a -> b -> SumTy a b
instance Add Integer Double where
type SumTy Integer Double = Double
plus x y = fromIntegral x + y
instance Add Double Integer where
type SumTy Double Integer = Double
plus x y = x + fromIntegral y
main :: IO ()
main = do
print $ plus (5::Integer) 6
print $ plus (5.0::Double) 6.0
the error message is:
app/Main.hs:25:3: error:
• Ambiguous type variable ‘b1’ arising from a use of ‘print’
prevents the constraint ‘(Show
(SumTy Integer b1))’ from being solved.
Probable fix: use a type annotation to specify what ‘b1’ should be.
These potential instances exist:
instance Show BS.ByteString
-- Defined in ‘Data.ByteString.Internal’
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
...plus 24 others
...plus 22 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of a 'do' block: print $ plus (5 :: Integer) 6
In the expression:
do print $ plus (5 :: Integer) 6
print $ plus (5.0 :: Double) 6.0
In an equation for ‘main’:
main
= do print $ plus (5 :: Integer) 6
print $ plus (5.0 :: Double) 6.0
|
25 | print $ plus (5::Integer) 6
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
what does Ambiguous type variable ‘b1’ arising from a use of ‘print’ mean? I can not see anywhere b1
.
Upvotes: 1
Views: 239
Reputation: 116174
plus (5::Integer) 6
The type of the first argument is Integer
. The type of the second one can be any numeric type, let's call that b1
, assuming Num b1
. So, we are calling the function
plus :: Integer -> b1 -> SumTy Integer b1
but there is no matching instance around. There's only an instance for Add Integer Double
, but we can't call that one, since after all the programmer later on might also add another instance for, say, Add Integer Integer
and we need to be ready for that one. (Note that the additional instance might even be in another module, so GHC can not simply assume it does not exist without checking all the modules, which would be inefficient.)
You need to specify the type for the 6
argument, otherwise the call is ambiguous.
Upvotes: 3
Reputation: 234
plus (5 :: Integer) 6
The compiler tries to infer the type of 6
, but fails. You have to specify the type of the number literal explicity, like that:
plus (5 :: Integer) (6 :: Double)
In order for the second plus
statement to compile, you cannot pass 6.0
, because this value is either a Float
or a Double
, and you do not have an instance of Add
defined for Double Double
. You can specify it's type as an Integer
, if that's what you want:
plus (5.0 :: Double) (6 :: Integer)
Upvotes: 2