Create a gist now

Instantly share code, notes, and snippets.

{-# 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