{-# LANGUAGE ExistentialQuantification #-} | |
-- interface Foo { | |
-- void doFoo(); | |
-- } | |
import Data.Char | |
-- A 'method' gets a this-ref, some args and a return type. | |
-- It will return an updated object and a return value | |
type Mthd clazz args ret = clazz -> args -> (clazz, ret) | |
-- the interface Foo's representation in haskell: | |
class Foo t where | |
doFoo :: Mthd t () () | |
newtype FooImpl1 = FooImpl1 Int deriving (Show) | |
instance Foo FooImpl1 where | |
this `doFoo` () = case this of | |
FooImpl1 i -> (FooImpl1 $ i+1, ()) | |
newtype FooImpl2 = FooImpl2 Char deriving(Show) | |
instance Foo FooImpl2 where | |
this `doFoo` () = case this of | |
FooImpl2 c -> (FooImpl2 $ toUpper c, ()) | |
data Dyn = forall rtty . (Foo rtty, Show rtty) => Dyn rtty | |
-- manual impl of subtype polymorphism: doFoo on Dyn calls the appropriate implementation: | |
instance Foo Dyn where | |
(Dyn this) `doFoo` () = case this `doFoo` () of | |
(updated, ()) -> (Dyn updated, ()) | |
instance Show Dyn where | |
show (Dyn x) = show x | |
heterogeneous_list = [Dyn (FooImpl1 1), | |
Dyn (FooImpl2 'a')] | |
main = do print $ map (`doFoo` ()) heterogeneous_list | |
-- question #1: I don't like that Dyn involves `Foo`. How could I abstract it out? | |
-- Ideally, I'd be getting something like `Dyn Foo` instead. | |
-- question #2: How can I avoid having to implement `instance Foo Dyn` myself? How could I generalise? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment