Hal Daume wrote: > -- *Main> test $ MkFoo (0::Int) > -- Just True > -- *Main> test $ MkBar 'a' > -- Just True
> i forgot to mention the constraint > that i don't want the user to have to use the MkFoo/MkBar > constructors. if i could use them internally to 'test', that would be > great, but that's what i couldn't get to work :). It can be done without burdening the user with typing MkFoo and MkBar. In fact, the enclosed code shows that it is possible to implement the dynamic dispatch on a type class context -- exactly the way you wanted it, it seems. The code resorts to no unsafe operations. Here's the test: -- *Main> test (1::Int) -- "this is foo calling: 1" -- *Main> test 'a' -- "this is bar calling: 'a'" -- *Main> test [True,False] -- "this is quu calling: [True,False]" Here's the code -- Dynamic dispatch on a constraint: Foo, Bar, or Quux -- The constraints to dispatch on class Foo a where { foo :: a -> String } class Bar a where { bar :: a -> String } class Quu a where { quu :: a -> String } -- Populate the type classes instance Foo Int where foo x = "this is foo calling: " ++ (show x) instance Bar Char where bar x = "this is bar calling: " ++ (show x) instance Quu [Bool] where quu x = "this is quu calling: " ++ (show x) -- The Universe (with hidden constraints) data PACK = forall a . Foo a => MkFoo a | forall a . Bar a => MkBar a | forall a . Quu a => MkQuu a -- The packer class Packable a where pack:: a -> PACK -- The following three instances seem to be the "inverse" -- of the "instance Foo Int" .. instance Quu [Bool] -- The three instances below do an important job: they "introduce" -- the class context, so to speak. -- Also, a type can be a member of several type classes. The following -- instances resolve the ambiguity. For example, even if Int were a member -- of a class Bar (in addition to being the member of a class Foo), the first -- instance declaration below resolves Int to a class Foo (and so we would -- dispatch on Foo when we see an Int). instance Packable Int where pack = MkFoo instance Packable Char where pack = MkBar instance Packable [Bool] where pack = MkQuu -- The dispatcher instance Foo PACK where foo (MkFoo x) = foo x instance Bar PACK where bar (MkBar x) = bar x instance Quu PACK where quu (MkQuu x) = quu x test:: (Packable a) => a -> String test = dispatch . pack where dispatch x = case x of (MkFoo a) -> foo a (MkBar a) -> bar a (MkQuu a) -> quu a -- *Main> test (1::Int) -- "this is foo calling: 1" -- *Main> test 'a' -- "this is bar calling: 'a'" -- *Main> test [True,False] -- "this is quu calling: [True,False]" _______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell