[Haskell] What is the best way to write adapters?

Ben_Yu at asc.aon.com Ben_Yu at asc.aon.com
Thu Mar 11 15:03:37 EST 2004

Thanks! Oleg.

This works and it looks nice!

And now, my code can be like:

class FwdSig d where
  (forall a. Sig a => a -> w) -> d -> w

All the types that supports such forwarding are instances of FwdSig.

My Def type is:

instance FwdSig Def where
  fwd f (ClassDef c) = f c
  fwd f (ProtDef p) = f p

instance Sig Def where
  getName = fwd getName
  getMethods = fwd getMethods

My Native type is:

instance FwdSig Native where
  fwd f (NativeSignature s) = f s
  fwd f (NativeProtocol p) = f p

instance Sig Native where
  getName = fwd getName
  getMethods = fwd getMethods

Many annoying forwarding functions are gone.

The only thing that I hope to be better is this "getXXX = fwd getXXX" piece
of code. Is it possible to reuse the same piece of code for both Native and
Def and any other possible types?

Inspired by your generic code, I wrote such thing:

instance FwdSig d => Sig d where
  getName = fwd getName
  getMethods = fwd getMethods

However, my ghc complains about the use of "Sig d".

I followed its recommendation and put -fallow-undecidable-instances flag
with the surprise that the "FwdSig d=>Sig d" instance declaration conflicts
with my other "instance Sig XXX" declarations.

Surely this is not a serious problem, I can live with repeating the
"getXXX=fwd getXXX" several times. Just curious about how further this can


oleg at pobox.com@haskell.org on 03/11/2004 01:36:30 PM

Please respond to oleg at pobox.com

Sent by:    haskell-bounces at haskell.org

To:    haskell at haskell.org
cc:    Ben_Yu at asc.aon.com

Subject:    [Haskell] What is the best way to write adapters?

> The code is currently like this:

> instance Sig Def where
>   getName (DefClass c) = getName c
>   getName(DefProtocol p) getName p
>   getName(DefSignature s) = getName s
>   getParents(DefClass c) = getParents c
>   getParents(DefProtocol p) = getParents p
> blah blah blah...
> But this seems very annoying.
> If I have 4 different constructors in Def, and 5 methods of class Sig,
> (Please bear with me if I'm using some OO terminology because I'm still a
> new FP programmer), I'll have to write 4*5=20 forwarding functions.

Adapters seem by necessity higher-ranked functions. The following is
a stubefied code that uses generic adaptors (the function fwd).

> {-# OPTIONS -fglasgow-exts #-}
> module Foo where
> class Sig a where
>   getName :: a -> Int
>   getParents :: a -> String
>   getMethods :: a -> String
> data ClassDef = ClassDef
> data ProtocolDef = ProtocolDef
> instance Sig ClassDef where
>     getName _ = 0
>     getParents _ = "ClassDef Parents"
>     getMethods _ = "ClassDef Methods"
> instance Sig ProtocolDef where
>     getName _ = 1
>     getParents _ = "ProtocolDef Parents"
>     getMethods _ = "ProtocolDef Methods"
> data Def = DefClass ClassDef | DefProtocol ProtocolDef
> fwd::(forall a. Sig a => a -> w) -> Def -> w
> fwd f (DefClass c) = f c
> fwd f (DefProtocol p) = f p
> instance Sig Def where
>     getName = fwd getName
>     getParents = fwd getParents
>     getMethods = fwd getMethods


*Foo> getParents ClassDef
"ClassDef Parents"
*Foo> getParents ProtocolDef
"ProtocolDef Parents"
*Foo> getParents (DefClass ClassDef)
"ClassDef Parents"
*Foo> getParents (DefProtocol ProtocolDef)
"ProtocolDef Parents"
Haskell mailing list
Haskell at haskell.org

This message is intended only for the addressee and may contain information
that is confidential or privileged. Unauthorized use is strictly prohibited
and may be unlawful. If you are not the intended recipient, or the person
responsible for delivering to the intended recipient, you should not read,
copy, disclose or otherwise use this message, except for the purpose of
delivery to the addressee. If you have received this email in error, please
delete and advise us immediately.

More information about the Haskell mailing list