Search code examples
haskellpolymorphismghci

GHCi different behavior for value with/without Show constraint


I was trying to understand what GHCi does to print values, I thought it would just do something like call putStrLn . show on the value, but then this happened:

a = return 5 :: (Monad m, Num a) => m a
a -- prints 5

b = return 5 :: (Monad m, Num a, Show (m a)) => m a
b -- Ambiguous type variable `m0`...

Why is it that adding the show constraint change this behavior? I thought that'd be assumed when trying to print the value.


Solution

  • By default ghci works in IO monad. So when you're trying to evaluate a its m type variable becomes IO. And a variable has type Num a => IO a. When you evaluate IO action inside repl, ghci just performs it and prints result. In your case this is Num a => a (and default for polymorphic variables with Num constraint in ghci is Integer data type).

    But IO data type doesn't have Show instance. There's no such instance and it can't even exist! Before evaluating some expression in ghci, it should satisfy all constraints. Since it can't satisfy Show (IO a) (because there's no such instance) it can't substitute IO for m type variable. But then: which m do you exactly want? ghci can't guess for you. Behaviour is different for different ms.

    ghci> b = return 5 :: (Monad m, Num a, Show (m a)) => m a
    ghci> b :: Maybe Int
    Just 5
    ghci> b :: [Int]
    [5]