Supplying a default implementation for a typeclass based on another class

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

Supplying a default implementation for a typeclass based on another class

Svein Ove Aas
I'm in the process of writing a distributed filesystem (in haskell,
yay), which of course means I'm using Binary for de/serialization.

Now, that's fine enough, but for simplicity (and for wireshark), I'd
like to be able to have Binary fall back on an instance based on
Show/Read for any type that lacks any other Binary instance..

Well, I understand why this would be somewhere between extremely hard
and impossible in haskell '98, but I'm not entirely up on all the
extensions, so I thought I'd ask - given every extension implemented
in ghc 6.10.1, is there any reasonable way to do this?
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Supplying a default implementation for a typeclass based on another class

Johan Jeuring
> Now, that's fine enough, but for simplicity (and for wireshark), I'd
> like to be able to have Binary fall back on an instance based on
> Show/Read for any type that lacks any other Binary instance..
>
> Well, I understand why this would be somewhere between extremely hard
> and impossible in haskell '98, but I'm not entirely up on all the
> extensions, so I thought I'd ask - given every extension implemented
> in ghc 6.10.1, is there any reasonable way to do this?

I'm not sure what you mean by falling back on Show/Read instances,
but this seems like a typical generic programming problem. Recent
releases include the EMGM and SYB libraries for generic programming.

-- Johan Jeuring

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Supplying a default implementation for a typeclass based on another class

Lennart Augustsson
In reply to this post by Svein Ove Aas
If you were writing your own Binary class you could simply make Show
and Read superclasses of Binary and it would be trivial to have
default implementations based on Show and Read.

  -- Lennart

On Sat, Feb 28, 2009 at 10:59 AM, Svein Ove Aas <[hidden email]> wrote:

> I'm in the process of writing a distributed filesystem (in haskell,
> yay), which of course means I'm using Binary for de/serialization.
>
> Now, that's fine enough, but for simplicity (and for wireshark), I'd
> like to be able to have Binary fall back on an instance based on
> Show/Read for any type that lacks any other Binary instance..
>
> Well, I understand why this would be somewhere between extremely hard
> and impossible in haskell '98, but I'm not entirely up on all the
> extensions, so I thought I'd ask - given every extension implemented
> in ghc 6.10.1, is there any reasonable way to do this?
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Supplying a default implementation for a typeclass based on another class

Svein Ove Aas
2009/2/28 Lennart Augustsson <[hidden email]>:
> If you were writing your own Binary class you could simply make Show
> and Read superclasses of Binary and it would be trivial to have
> default implementations based on Show and Read.
>
That's my fallback approach, yes, but I don't really want to make
Binary a subclass of Show,Read. I'd like to be able to define this for
classes in packages I *don't* control, and without *requiring* the
fallback to work..

As you say, it isn't exactly a critical issue. I was just wondering if
it was possible, really.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Supplying a default implementation for a typeclass based on another class

sclv
In reply to this post by Svein Ove Aas
On Feb 28, 2009, at 5:59 AM, Svein Ove Aas wrote:

> I'm in the process of writing a distributed filesystem (in haskell,
> yay), which of course means I'm using Binary for de/serialization.
>
> Now, that's fine enough, but for simplicity (and for wireshark), I'd
> like to be able to have Binary fall back on an instance based on
> Show/Read for any type that lacks any other Binary instance.

Rather than something funny with extensions, why not write two  
methods, of type

defBinaryPut :: Show a => a -> Put
defBinaryGet :: Read a => Get a

Then, if somebody tries to use something lacking a Binary instance,  
they can just define a simple instance with those two methods. And  
when they want to improve performance, they just write better  
methods. :-)

In fact, these seem useful enough to go into, if not Data.Binary  
itself, a separate package. After all, proper serialization shouldn't  
be a barrier to rapid prototyping.

Cheers,
S.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Supplying a default implementation for a typeclass based on another class

Martin Huschenbett
In reply to this post by Svein Ove Aas
Hi,

you could do something like

 > instance (Show a,Read a) => Binary a where
 >  put = put . show
 >  get = fmap read get

But then you will need the following language extensions:
FlexibleInstances, OverlappingInstances, UndecidableInstances

I don't know how safe this is but it seems to work.

Regards,

Martin.

Svein Ove Aas schrieb:

> I'm in the process of writing a distributed filesystem (in haskell,
> yay), which of course means I'm using Binary for de/serialization.
>
> Now, that's fine enough, but for simplicity (and for wireshark), I'd
> like to be able to have Binary fall back on an instance based on
> Show/Read for any type that lacks any other Binary instance..
>
> Well, I understand why this would be somewhere between extremely hard
> and impossible in haskell '98, but I'm not entirely up on all the
> extensions, so I thought I'd ask - given every extension implemented
> in ghc 6.10.1, is there any reasonable way to do this?
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Supplying a default implementation for a typeclass based on another class

Svein Ove Aas
On Sun, Mar 1, 2009 at 6:42 PM, Martin Huschenbett <[hidden email]> wrote:

> Hi,
>
> you could do something like
>
>> instance (Show a,Read a) => Binary a where
>>  put = put . show
>>  get = fmap read get
>
> But then you will need the following language extensions: FlexibleInstances,
> OverlappingInstances, UndecidableInstances
>
Well, isn't there a good chance it'll end up picking that instance
even when a more specific one is available, then?

I think the problem here is that I don't know of any way to inform GHC
that any particular instance is "less specific".
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Supplying a default implementation for a typeclass based on another class

wren ng thornton
Svein Ove Aas wrote:

> Martin Huschenbett wrote:
> >
> >> instance (Show a,Read a) => Binary a where
> >>  put = put . show
> >>  get = fmap read get
> > But then you will need the following language extensions: FlexibleInstances,
> > OverlappingInstances, UndecidableInstances
>
> Well, isn't there a good chance it'll end up picking that instance
> even when a more specific one is available, then?
>
> I think the problem here is that I don't know of any way to inform GHC
> that any particular instance is "less specific".

OverlappingInstances will allow more specific instances to be defined,
and will select them when appropriate. Where "specific" has to do with
the usual type unification algorithm. This instance is on a type
variable, hence is the least specific. An instance on (Maybe a), (Either
a b), etc would all be more specific. Instances on (Maybe Int), (Either
Bool b), (Either a Double) would be more specific still.

Aside: Depending on how you're using this, we can run into problems
with, say, (Either Bool Double). Does it fall under (Either Bool b) or
under (Either a Double)? By default, OverlappingInstances requires that
you manually resolve this diamond issue (i.e. by defining an instance
for (Either Bool Double) which is more specific than all other options).
The IncoherentInstances option tells the compiler to deal with the
ambiguity itself, which means it will pick the most specific instance
which does not introduce ambiguity (i.e. the other end of the diamond;
in this case, the instance for the fully unspecified type variable).
Obviously, incoherence generally does not mean what you want.

The UndecidableInstances is because the two elements of the context are
not "smaller" than the head (Binary a), and hence the compiler cannot
guarantee that progress is being made when it backward-chains to find
those instances. To witness why this could be a problem, imagine an
instance for Show or Read which took Binary in the context.

--
Live well,
~wren
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe