Overlapping instances: are functions and typeclass methods treated differently?

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

Overlapping instances: are functions and typeclass methods treated differently?

Daniel Díaz Carrete
Hi,

I have a question about overlapping instances, prompted by this Stack Overflow question: https://stackoverflow.com/questions/64220161/interaction-of-multiple-overlapping-instances

Consider this code (never mind how sensible would it be to write):

> {-# LANGUAGE FlexibleInstances #-}
> newtype Foo = Foo Int
> instance {-# OVERLAPS #-} Show (Maybe Foo) where
>   show _ = "maybe foo"

And this function:

> foo :: Show a => Maybe a -> String
> foo = show

The function gives a compilation error about overlapping instances: 

> * Overlapping instances for Show (Maybe a)
>     arising from a use of `show'
>   Matching instances:
>     instance Show a => Show (Maybe a) -- Defined in `GHC.Show'
>     instance [overlap ok] Show (Maybe Foo) -- Defined at Main.hs:3:27
>   (The choice depends on the instantiation of `a'

I believe the relevant part in the GHC User Guide that explains the error is the following:

> Now find all instances, or in-scope given constraints, that unify with the target constraint, but do not match it. Such non-candidate instances might match when the target constraint is further instantiated. If all of them are incoherent top-level instances, the search succeeds, returning the prime candidate. Otherwise the search fails.

https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html?highlight=overlappinginstances#overlapping-instances

I think I understand this, although the meaning of "unify vs. match" is not completely clear.  

But now consider this instance:

> newtype Wrapper a = Wrapper (Maybe a)
> instance Show a => Show (Wrapper a) where
>   show (Wrapper x) = show x

This compiles just fine, despite—to my mind—suffering from the exact same problem that the "foo" function had. Why does it work?

Daniel

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Overlapping instances: are functions and typeclass methods treated differently?

Henning Thielemann

On Thu, 8 Oct 2020, Daniel Díaz wrote:

> But now consider this instance:
>
> > newtype Wrapper a = Wrapper (Maybe a)
> > instance Show a => Show (Wrapper a) where
> >   show (Wrapper x) = show x
>
> This compiles just fine, despite—to my mind—suffering from the exact same problem that the "foo" function had.
> Why does it work?

There is an instance Show (Maybe a) in Prelude, but no instance Show
(Wrapper a), so no overlapping.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Overlapping instances: are functions and typeclass methods treated differently?

Daniel Díaz Carrete
On Thu, Oct 8, 2020 at 2:12 PM Henning Thielemann <[hidden email]> wrote:

On Thu, 8 Oct 2020, Daniel Díaz wrote:

> But now consider this instance:
>
> > newtype Wrapper a = Wrapper (Maybe a)
> > instance Show a => Show (Wrapper a) where
> >   show (Wrapper x) = show x
>
> This compiles just fine, despite—to my mind—suffering from the exact same problem that the "foo" function had.
> Why does it work?

There is an instance Show (Maybe a) in Prelude, but no instance Show
(Wrapper a), so no overlapping.

Sorry, I wasn't very clear there.

The problem is not with the "Show (Wrapper a)" instance itself, but with its implementation of "show". It depends (just as the function "foo" did) on "Show (Maybe a)", for which there are overlapping instances.

And yet "foo" compiles without problem, while the typeclass method doesn't. 


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Overlapping instances: are functions and typeclass methods treated differently?

norc foobar
Hi Daniel,

The constraint on an instance declaration is, perhaps counterintuitively, discharged at the usage site rather than the definition site.

foo :: Show a => Wrapper a -> String
foo (Wrapper a) = show a

will produce the aforementioned diagnostic.

---
Victor

On Fri, Oct 9, 2020 at 2:51 PM Daniel Díaz <[hidden email]> wrote:
On Thu, Oct 8, 2020 at 2:12 PM Henning Thielemann <[hidden email]> wrote:

On Thu, 8 Oct 2020, Daniel Díaz wrote:

> But now consider this instance:
>
> > newtype Wrapper a = Wrapper (Maybe a)
> > instance Show a => Show (Wrapper a) where
> >   show (Wrapper x) = show x
>
> This compiles just fine, despite—to my mind—suffering from the exact same problem that the "foo" function had.
> Why does it work?

There is an instance Show (Maybe a) in Prelude, but no instance Show
(Wrapper a), so no overlapping.

Sorry, I wasn't very clear there.

The problem is not with the "Show (Wrapper a)" instance itself, but with its implementation of "show". It depends (just as the function "foo" did) on "Show (Maybe a)", for which there are overlapping instances.

And yet "foo" compiles without problem, while the typeclass method doesn't. 

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Overlapping instances: are functions and typeclass methods treated differently?

David Feuer
That's not the same, because you show what's under the wrapper, rather than the wrapped value.

On Mon, Oct 12, 2020, 8:28 PM norc foobar <[hidden email]> wrote:
Hi Daniel,

The constraint on an instance declaration is, perhaps counterintuitively, discharged at the usage site rather than the definition site.

foo :: Show a => Wrapper a -> String
foo (Wrapper a) = show a

will produce the aforementioned diagnostic.

---
Victor

On Fri, Oct 9, 2020 at 2:51 PM Daniel Díaz <[hidden email]> wrote:
On Thu, Oct 8, 2020 at 2:12 PM Henning Thielemann <[hidden email]> wrote:

On Thu, 8 Oct 2020, Daniel Díaz wrote:

> But now consider this instance:
>
> > newtype Wrapper a = Wrapper (Maybe a)
> > instance Show a => Show (Wrapper a) where
> >   show (Wrapper x) = show x
>
> This compiles just fine, despite—to my mind—suffering from the exact same problem that the "foo" function had.
> Why does it work?

There is an instance Show (Maybe a) in Prelude, but no instance Show
(Wrapper a), so no overlapping.

Sorry, I wasn't very clear there.

The problem is not with the "Show (Wrapper a)" instance itself, but with its implementation of "show". It depends (just as the function "foo" did) on "Show (Maybe a)", for which there are overlapping instances.

And yet "foo" compiles without problem, while the typeclass method doesn't. 

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.