It is common to come across error messages that have a0
in them (or similar type variables p1
, t0
, etc.) and I am always wondering what specifically they refer to. Here is an example.
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE InstanceSigs #-}
module Expr1 where
import TextShow ( showbParen, Builder, TextShow(showb, showbPrec) )
data Expr a = Lit a
| Add (Expr a) (Expr a)
| Mult (Expr a) (Expr a)
deriving (Show, Read)
instance TextShow a => TextShow (Expr a) where
showbPrec :: Int -> Expr a -> Builder
showbPrec p e =
case e of
Lit a -> showb a
Add e1 e2 -> showbHelper p 5 "+" e1 e2
Mult e1 e2 -> showbHelper p 6 "*" e1 e2
showbHelper :: (TextShow a) => Int -> Int -> Builder -> Expr a -> Expr a -> Builder
showbHelper outerPrec thisPrec op e1 e2 =
showbParen (outerPrec > thisPrec)
$ showbPrec thisPrec e1 <> op <> showbPrec thisPrec e2
plus :: Builder
plus = "+"
expr1 :: Expr Integer
expr1 = Add (Lit 2) (Lit 3)
expr2 :: Expr Integer
expr2 = Mult (Lit 4) (Lit 5)
bb1 = showbParen (True) $ showbPrec 6 expr1
<> plus
<> showbPrec 5 expr2
All is good here but I wanted to substitute in the value for expr1
and expr2
and tried this first:
bb1 = showbParen (True)
$ showbPrec 6 (Add (Lit 2) (Lit 3))
<> plus
<> showbPrec 5 expr2
And got the below error with the entire line showbPrec 6 (Add (Lit 2) (Lit 3))
underlined. (I’m using VSCode with HLS)
• Ambiguous type variable ‘a0’ arising from a use of ‘showbPrec’
prevents the constraint ‘(TextShow a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance (TextShow a, TextShow b) => TextShow (Either a b)
-- Defined in ‘TextShow.Data.Either’
instance TextShow Ordering -- Defined in ‘TextShow.Data.Ord’
instance TextShow a => TextShow (Expr a)
-- Defined at /home/klequis/d/learn/haskell/book/haskell-in-depth/mini-proj/expr/app/Expr1.hs:13:10
...plus 26 others
...plus 208 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the first argument of ‘(<>)’, namely
‘showbPrec 6 (Add (Lit 2) (Lit 3))’
In the second argument of ‘($)’, namely
‘showbPrec 6 (Add (Lit 2) (Lit 3)) <> plus <> showbPrec 5 expr2’
In the expression:
showbParen (True)
$ showbPrec 6 (Add (Lit 2) (Lit 3)) <> plus <> showbPrec 5 expr2typecheck(-Wdeferred-type-errors)
It wasn’t immediately clear to me what a0
was.
Only figuring out the fix is adding the type for Add (Lit 2) (Lit 3)
– [A] …
bb1 = showbParen (True)
$ showbPrec 6 (Add (Lit 2) (Lit 3) :: Expr Int) -- [A]
<> plus
<> showbPrec 5 expr2
… did I see that a0
is probably the second argument to showbPrec
(is that correct?)
:t showbPrec
showbPrec :: TextShow a => Int -> a -> Builder
Is that the process for figuring out the error message or am I missing something that makes it more straight forward to know what a0
is?
Edit: Perhaps one good answer to that would be how you approach or think through error messages.