Why doesn't ghci provide the expected Ambiguous type variable error in this scenario? - haskell

I'm working through a Haskell book. It has the following example:
ghci> Right 3 >>= \x -> return (x + 100)
It expects that this blows up with this error:
<interactive>:1:0:
Ambiguous type variable `a' in the constraints:
`Error a' arising from a use of `it' at <interactive>:1:0-33
`Show a' arising from a use of `print' at <interactive>:1:0-33
Probable fix: add a type signature that fixes these type variable(s)
When I run it:
$ ghci
Prelude> Right 3 >>= \x -> return (x + 100)
I get:
Right 103
ie I don't get the error expected.
Now maybe the compiler or the library has changed - but I'm not sure how to verify that.
My question is: Why doesn't ghci provide the expected Ambiguous type variable error in this scenario?

This is due to -XExtendedDefaultRules being now enabled by default in GHCi. To turn it off (and get your expected error message):
ghci> :set -XNoExtendedDefaultRules
ghci> Right 3 >>= \x -> return (x + 100)
<interactive>:2:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance (Show b, Show a) => Show (Either a b)
-- Defined in ‘Data.Either’
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
...plus 23 others
...plus 11 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of an interactive GHCi command: print it
This extension adds a bunch of extra ways to default otherwise ambiguous code. In your case, you have an expression of type Num b => Either a b. Regular Haskell defaulting rules tell us the b should default to Integer. The extended rules (see the link above) additionally default a to ().

Related

Problem when defining Int as an instance of a type class in Haskell

I am trying to define Int as an instance of my type class Add.
I wanted to define my own operator +++, which should be overloaded on integers and strings. My goal was to be able to add integers and concatenate strings with the same operator. Therefore i created the type class Add with the instances Int and [char]:
class Add a where
(+++) :: a -> a -> a
instance Add Int where
x +++ y = x + y
instance Add [char] where
x +++ y = x ++ y
Problem: When evaluating the expression 1 +++ 2, GHCi gives me the following error message:
<interactive>:9:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 18 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of an interactive GHCi command: print it
But when defining Integer as an instance of Add
instance Add Integer where
x +++ y = x + y
GHCi can evaluate 1 +++ 2 to 3 and i don't get an error.
Question: Why is it not working, when using Int as an instance? What is the difference in using Int or Integer?
Given that it works for Integer but not Int, I'm fairly sure this is due to "type defaulting".
In GHCi (and to a lesser extent in compiled code), if an expression has an ambiguous type, the compiler tries several "default types", which of which is Integer (but not Int). That's almost certainly where the difference is coming from.
I suspect if you add :: Int to the end of your expression, it will execute just fine. The problem isn't that there's a type error, it's that more than one type potentially fits, and the compiler isn't sure which one you intended.
I've never tried this, but I believe you can change the defaults by saying something like default (Int, Double). (Usually it's default (Integer, Double).) I think that's the right syntax; not 100% sure.
There's a bit about this in the GHCi manual: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#type-defaulting-in-ghci
Also the Haskell Report: https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-750004.3 (Section 4.3.4)

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

I have the following data structure, and I am trying to write a printer for it:
data CTypeF a
= CVarF Int
| CArrF a a
| CIntF
| CBoolF
deriving (Eq, Data, Show, Functor, Foldable, Traversable)
The following gives me an error:
my_test = do
let c0 = CIntF
(print CIntF)
This is the error message:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Constr -- Defined in ‘Data.Data’
instance Show ConstrRep -- Defined in ‘Data.Data’
instance Show DataRep -- Defined in ‘Data.Data’
...plus 40 others
...plus 166 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of a 'do' block: (print CIntF)
In the expression:
do let c0 = CIntF
(print CIntF)
I saw the following question Ambiguous type variable ‘b1’ arising from a use of ‘print’
and modified my code to do (print CIntF :: CTypeF) but I get:
• Expecting one more argument to ‘CTypeF’
Expected a type, but ‘CTypeF’ has kind ‘* -> *’
I am a bit lost on what the issue is. Could someone point out what I'm doing wrong here?
As the error message says, CTypeF takes an argument. CTypeF is not a type, but e.g. CTypeF () or CTypeF Int or CTypeF [(String, Double)] are.
The situation is analogous to print Nothing and attempting to fix it by adding (Nothing :: Maybe). You need to specify Maybe () or Maybe Int or ...
Try
my_test = do
let c0 = CIntF :: CTypeF ()
print c0
The issue is that, as Haskell sees it, you havent told it what the a in CTypeF a is, at least not enough to print it. You might try print (CIntF :: CTypeF ()).

Why can't Haskell function return a list

What is wrong with that:
partin a = [floor a, a-floor a]
Error :
<interactive>:342:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 16 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of an interactive GHCi command: print it
I can't give a complete answer without seeing the full extent of what you're doing, but here's one definite problem that is almost certainly involved. You write
partin a = [floor a, a-floor a]
The type of floor is
floor :: (RealFrac a, Integral b) => a -> b
The type of (-) is
(-) :: Num a => a -> a -> a
Since you use a - floor a, you're forcing the type of a to be an instance of both the RealFrac class and the Integral class. However, there is no such type in the standard library (and it doesn't make a lot of sense). As a result, GHC certainly will not be able to select the type for you from its very limited collection of defaults. Things might work out a lot better if you use
partin a = [fromIntegral (floor a), a - fromIntegral (floor a :: Int)]
But note that it doesn't really make much sense to have a list here, since you're trying to divide a number into two components of different types. You might be better off with
partin a = (floor a, a - fromIntegral (floor a :: Int))

Print empty list in Haskell [duplicate]

This question already has an answer here:
Print empty list in Haksell
(1 answer)
Closed 6 years ago.
This is haskell code. I'm finding why I am wrong with below.
main = do
print [1] -- Okay
print [] -- error
Error strings are following.
P07.hs:38:11: error:
? Ambiguous type variable ‘t0’ arising from a use of ‘print’
prevents the constraint ‘(Show t0)’ from being solved.
Probable fix: use a type annotation to specify what ‘t0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus five instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
? In a stmt of a 'do' block: print []
In the expression: do { print [] }
In an equation for ‘main’: main = do { print [] }
I tried [] :: Show not working. I think I just don't know what the errors mean.. please help me.
Thanks.
Lists in Haskell are polymorphic in their element's type and as [] contains not enough information you have to supply ghc with it by explicitly giving a type annotation [] :: [Int] for example.
The error you are getting is due to the fact that the Show instance for lists is depending on the Show instance for its elements, and as ghc cannot determine that it assumes that ist has no such instance.
Now you might think everything can be converted to a String, but then you could think of Int -> Int and try
show [(+1)]
Which will not work as functions in Haskell have no default Show instance.

Is there a way to make GHC provide the type class constraints of typed holes?

Current behavior
Prelude> show _
<interactive>:7:6:
Found hole ‘_’ with type: a0
Where: ‘a0’ is an ambiguous type variable
Relevant bindings include it :: String (bound at <interactive>:7:1)
In the first argument of ‘show’, namely ‘_’
In the expression: show _
In an equation for ‘it’: it = show _
Desired behavior
It would be nice if GHC would also tell me that the typed hole has the Show type class constraint.
Misc
GHC Version 7.8.1
This is now fixed in GHC 8.0 thanks to #DominiqueDevriese's GHC ticket.
Due to extended type defaulting, this isn't immediately obvious in GHCi. With your example,
> show _
<interactive>:7:6: error:
• Found hole: _h :: ()
Or perhaps ‘_h’ is mis-spelled, or not in scope
• In the first argument of ‘show’, namely ‘_h’
In the expression: show _h
In an equation for ‘it’: it = show _h
• Relevant bindings include
it :: String (bound at <interactive>:7:1)
the type of the hole is defaulted to (). This is apparently the desired behavior, though there's an argument to be made that extended defaulting shouldn't apply to holes (as a common use for them is to get the compiler to tell you the inferred type).
Nevertheless, if you compile with GHC or disable extended default rules in GHCi (via :set -XNoExtendedDefaultRules), we see the result of the improvements:
<interactive>:3:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘show’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 11 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: show _
In an equation for ‘it’: it = show _
<interactive>:3:6: error:
• Found hole: _ :: a0
Where: ‘a0’ is an ambiguous type variable
• In the first argument of ‘show’, namely ‘_’
In the expression: show _
In an equation for ‘it’: it = show _
• Relevant bindings include
it :: String (bound at <interactive>:3:1)
No currently its not possible.But it may be added to GHC as per the speculations.
Try it :: _ => _ in GHC 8.8+.

Resources