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 go. Ben. oleg@pobox.com@haskell.org on 03/11/2004 01:36:30 PM Please respond to oleg@pobox.com Sent by: haskell-bounces@haskell.org To: haskell@haskell.org cc: Ben_Yu@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
Tests: *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@haskell.org http://www.haskell.org/mailman/listinfo/haskell 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.