Re: [Haskell-beginners] Ambiguous type variable

I'm sure it makes sense! I'm not really following though. I understood typeclasses to be analogous to OO interfaces. So if a variable implements the Exception interface, and Exception implements the Show interface, then it should automatically support show. I take it this was wrong? How does the compiler use typeclasses if they're not interfaces? Francesco Ariis wrote:
I'm trying to use catch (...) (\e -> putStrLn $ show e) However, I get an error Ambiguous type variable ‘a0’ arising from a use of ‘show’ prevents the constraint ‘(Show a0)’ from being solved. This goes away if I change the code to catch (...) (\e -> putStrLn $ show (e::IOException))
A couple of things I don't understand here: - The signature for catch begins "Exception e", and exception it "class (Typeable e, Show e) => Exception e". So why isn't show automatically available? - Why does the new code work at all? e is Exception, not IOException. What would happen if it caught a different Exception?
IOException is a concrete type while Exception is a typeclass. In the end, the compiler needs the former, the latter not being enough. The code works as any other class-based function would someFunction :: Monoid a -> [a] -> a -- ^-- in the end `Monoid a` will become something concrete, like -- a String, a Sum, etc. Does that make sense?

Hi Jonathon!
You only catch some specific type of exception, everything else is simply
past onwards. See end of p. 2/beginning of p. 3 here:
http://community.haskell.org/~simonmar/papers/ext-exceptions.pdf
On Thu, Aug 17, 2017 at 2:24 PM, Jonathon Delgado
I'm sure it makes sense! I'm not really following though.
I understood typeclasses to be analogous to OO interfaces. So if a variable implements the Exception interface, and Exception implements the Show interface, then it should automatically support show.
I take it this was wrong? How does the compiler use typeclasses if they're not interfaces?
Francesco Ariis wrote:
I'm trying to use catch (...) (\e -> putStrLn $ show e) However, I get an error Ambiguous type variable ‘a0’ arising from a use of ‘show’ prevents the constraint ‘(Show a0)’ from being solved. This goes away if I change the code to catch (...) (\e -> putStrLn $ show (e::IOException))
A couple of things I don't understand here: - The signature for catch begins "Exception e", and exception it "class (Typeable e, Show e) => Exception e". So why isn't show automatically available? - Why does the new code work at all? e is Exception, not IOException. What would happen if it caught a different Exception?
IOException is a concrete type while Exception is a typeclass. In the end, the compiler needs the former, the latter not being enough.
The code works as any other class-based function would
someFunction :: Monoid a -> [a] -> a -- ^-- in the end `Monoid a` will become something concrete, like -- a String, a Sum, etc.
Does that make sense? _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Markus Läll

On Thu, Aug 17, 2017 at 12:24:07PM +0000, Jonathon Delgado wrote:
I'm sure it makes sense! I'm not really following though.
I understood typeclasses to be analogous to OO interfaces. So if a variable implements the Exception interface, and Exception implements the Show interface, then it should automatically support show.
I take it this was wrong? How does the compiler use typeclasses if they're not interfaces?
That's correct! Indeed ghc is not complaining about a lack of instances, as it would with, say λ> putStrLn 5 -- • No instance for (Num String) arising from etc etc. but about the *ambiguity* of type variable `e`. How does `catch` know _which_ exception to deal with if you don't specify the concrete type? Consider: prova = catch (print $ div (error "hey bby") 0) (\e -> print "ouch" >> print (e :: ErrorCall)) -- I want to deal with arithmetic errors here and not in `prova` palla = catch prova (\e -> print "baaah" >> print (e :: ArithException)) If I switch ArithException and ErrorCall the behaviour of invoking `palla` changes. Having a catch-all `catch` is possible by using (e :: SomeException); if you don't care about `e` and just want to do an action regardless, you are probably better off with `onException`. Ask more if needed!

On Thu, Aug 17, 2017 at 4:29 PM, Francesco Ariis
I'm sure it makes sense! I'm not really following though.
I understood typeclasses to be analogous to OO interfaces. So if a variable implements the Exception interface, and Exception implements the Show interface, then it should automatically support show.
I take it this was wrong? How does the compiler use typeclasses if
On Thu, Aug 17, 2017 at 12:24:07PM +0000, Jonathon Delgado wrote: they're
not interfaces?
That's correct! Indeed ghc is not complaining about a lack of instances, as it would with, say
λ> putStrLn 5 -- • No instance for (Num String) arising from etc etc.
but about the *ambiguity* of type variable `e`. How does `catch` know _which_ exception to deal with if you don't specify the concrete type? Consider:
prova = catch (print $ div (error "hey bby") 0) (\e -> print "ouch" >> print (e :: ErrorCall))
-- I want to deal with arithmetic errors here and not in `prova` palla = catch prova (\e -> print "baaah" >> print (e :: ArithException))
If I switch ArithException and ErrorCall the behaviour of invoking `palla` changes.
Having a catch-all `catch` is possible by using (e :: SomeException); if you don't care about `e` and just want to do an action regardless, you are probably better off with `onException`.
This is dangerous: `catch` with `e :: SomeException` will catch all asynchronous exceptions, breaking things like timeout, race, and the async library in general. That's why my message about mentioned the safe-exceptions package. Michael
Ask more if needed! _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
participants (4)
-
Francesco Ariis
-
Jonathon Delgado
-
Markus Läll
-
Michael Snoyman