softshipper
softshipper

Reputation: 34099

Ambiguous type variable ‘b1’ arising from a use of ‘print’

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

Answers (2)

chi
chi

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

kon.simeonov
kon.simeonov

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

Related Questions