Re: Ambiguous type variable

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous type variable

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
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous type variable

Markus Läll-2
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 <[hidden email]> 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?


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
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners



--
Markus Läll

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous type variable

Francesco Ariis
In reply to this post by Jonathon Delgado
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!
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous type variable

Michael Snoyman


On Thu, Aug 17, 2017 at 4:29 PM, Francesco Ariis <[hidden email]> wrote:
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`.


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
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous type variable

Jonathon Delgado
In reply to this post by Jonathon Delgado
Thank you very much, that does clarify things!

Francesco Ariis  wrote:

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!
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners