Problem when defining Int as an instance of a type class in Haskell - 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)

Related

Why such different behaviour with `Ambiguous type..` error (in ghci)?

This example works with ghci, load this file:
import Safe
t1 = tailMay []
and put in ghci:
> print t1
Nothing
But if we add analogous definition to previous file, it doesn't work:
import Safe
t1 = tailMay []
t2 = print $ tailMay []
with such 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
That is 3rd sample for ghc with the same error:
import Safe
t1 = tailMay
main = do
print $ t1 []
print $ t1 [1,2,3]
Why? And how to fix the second sample without explicit type annotation?
The issue here is that tailMay [] can generate an output of type Maybe [a] for any a, while print can take an input of type Maybe [a] for any a (in class Show).
When you compose a "universal producer" and a "universal consumer", the compiler has no idea about which type a to pick -- that could be any type in class Show. The choice of a could matter since, in principle, print (Nothing :: Maybe [Int]) could print something different from print (Nothing :: Maybe [Bool]). In this case, the printed output would be the same, but only because we are lucky.
For instance print ([] :: [Int]) and print ([] :: [Char]) will print different messages, so print [] is ambiguous. Hence, GHC reject it, and requires an explicit type annotation (or a type application # type, using an extension).
Why, then, such ambiguity is accepted in GHCi? Well, GHCi is meant to be used for quick experiments, and as such, as a convenience feature, it will try hard to default these ambiguous a. This is done using the extended defaulting rules, which could (I guess) in principle be turned on in GHC as well by turning on that extension.
This is, however, not recommended since sometimes the defaulting rule can choose some unintended type, making the code compile but with an unwanted runtime behavior.
The common solution to this issue is using an annotation (or # type), because it provides more control to the programmer, makes the code easier to read, and avoids surprises.

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

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 ().

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.

How to work around issue with ambiguity when monomorphic restriction turned *on*?

So, learning Haskell, I came across the dreaded monomorphic restriction, soon enough, with the following (in ghci):
Prelude> let f = print.show
Prelude> f 5
<interactive>:3:3:
No instance for (Num ()) arising from the literal `5'
Possible fix: add an instance declaration for (Num ())
In the first argument of `f', namely `5'
In the expression: f 5
In an equation for `it': it = f 5
So there's a bunch of material about this, e.g. here, and it is not so hard to workaround.
I can either add an explicit type signature for f, or I can turn off the monomorphic restriction (with ":set -XNoMonomorphismRestriction" directly in ghci, or in a .ghci file).
There's some discussion about the monomorphic restriction, but it seems like the general advice is that it is ok to turn this off (and I was told that this is actually off by default in newer versions of ghci).
So I turned this off.
But then I came across another issue:
Prelude> :set -XNoMonomorphismRestriction
Prelude> let (a,g) = System.Random.random (System.Random.mkStdGen 4) in a :: Int
<interactive>:4:5:
No instance for (System.Random.Random t0)
arising from the ambiguity check for `g'
The type variable `t0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance System.Random.Random Bool -- Defined in `System.Random'
instance System.Random.Random Foreign.C.Types.CChar
-- Defined in `System.Random'
instance System.Random.Random Foreign.C.Types.CDouble
-- Defined in `System.Random'
...plus 33 others
When checking that `g' has the inferred type `System.Random.StdGen'
Probable cause: the inferred type is ambiguous
In the expression:
let (a, g) = System.Random.random (System.Random.mkStdGen 4)
in a :: Int
In an equation for `it':
it
= let (a, g) = System.Random.random (System.Random.mkStdGen 4)
in a :: Int
This is actually simplified from example code in the 'Real World Haskell' book, which wasn't working for me, and which you can find on this page: http://book.realworldhaskell.org/read/monads.html (it's the Monads chapter, and the getRandom example function, search for 'getRandom' on that page).
If I leave the monomorphic restriction on (or turn it on) then the code works. It also works (with the monomorphic restriction on) if I change it to:
Prelude> let (a,_) = System.Random.random (System.Random.mkStdGen 4) in a :: Int
-106546976
or if I specify the type of 'a' earlier:
Prelude> let (a::Int,g) = System.Random.random (System.Random.mkStdGen 4) in a :: Int
-106546976
but, for this second workaround, I have to turn on the 'scoped type variables' extension (with ":set -XScopedTypeVariables").
The problem is that in this case (problems when monomorphic restriction on) neither of the workarounds seem generally applicable.
For example, maybe I want to write a function that does something like this and works with arbitrary (or multiple) types, and of course in this case I most probably do want to hold on to the new generator state (in 'g').
The question is then: How do I work around this kind of issue, in general, and without specifying the exact type directly?
And, it would also be great (as a Haskell novice) to get more of an idea about exactly what is going on here, and why these issues occur..
When you define
(a,g) = random (mkStdGen 4)
then even if g itself is always of type StdGen, the value of g depends on the type of a, because different types can differ in how much they use the random number generator.
Moreover, when you (hypothetically) use g later, as long as a was polymorphic originally, there is no way to decide which type of a you want to use for calculating g.
So, taken alone, as a polymorphic definition, the above has to be disallowed because g actually is extremely ambiguous and this ambiguity cannot be fixed at the use site.
This is a general kind of problem with let/where bindings that bind several variables in a pattern, and is probably the reason why the ordinary monomorphism restriction treats them even stricter than single variable equations: With a pattern, you cannot even disable the MR by giving a polymorphic type signature.
When you use _ instead, presumably GHC doesn't worry about this ambiguity as long as it doesn't affect the calculation of a. Possibly it could have detected that g is unused in the former version, and treated it similarly, but apparently it doesn't.
As for workarounds without giving unnecessary explicit types, you might instead try replacing let/where by one of the binding methods in Haskell which are always monomorphic. The following all work:
case random (mkStdGen 4) of
(a,g) -> a :: Int
(\(a,g) -> a :: Int) (random (mkStdGen 4))
do (a,g) <- return $ random (mkStdGen 4)
return (a :: Int) -- The result here gets wrapped in the Monad

Resources