Reputation: 779
I'm trying to compile simple code snippet.
main = (putStrLn . show) (Right 3.423)
Compile results in the following error:
No instance for (Show a0) arising from a use of `show'
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 Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 42 others
In the second argument of `(.)', namely `show'
In the expression: putStrLn . show
In the expression: (putStrLn . show) (Right 3.423)
When i execute same snippet from ghci everything works as expected.
Prelude> let main = (putStrLn . show) (Right 3.423)
Prelude> main
Right 3.423
So the question is what is going on?
Upvotes: 0
Views: 92
Reputation: 54058
The problem is that GHC can't determine what the full type of Right 3.423
is, it can only determine that it has the type Either a Double
, and the instance of Show
for Either
looks like instance (Show a, Show b) => Show (Either a b)
. Without that extra constraint on Either a Double
, GHC doesn't know how to print it.
The reason why it works in interactive mode is because of the dreaded monomorphism restriction, which makes GHCi more aggressive in the defaults it chooses. This can be disabled with :set -XNoMonomorphismRestriction
, and that is going to become the default in future versions of GHC since it causes a lot of problems for beginners.
The solution to this problem is to put a type signature on Right 3.423
in your source code, like
main = (putStrLn . show) (Right 3.423 :: Either () Double)
Here I've just used ()
for a
, since we don't care about it anyway and it's the "simplest" type that can be shown. You could put String
or Int
or Double
or whatever you want there, so long as it implements Show
.
A tip, putStrLn . show
is exactly the definition of print
, so you can just do
main = print (Right 3.423 :: Either () Double)
As @ØrjanJohansen points out, this is not the monomorphism restriction, but rather the ExtendedDefaultRules
extension that GHCi uses, which essentially does exactly what I did above and shoves ()
into type variables to make things work in the interactive session.
Upvotes: 6