Not sure what you mean, exactly. Could you sketch a simple example with some types and typeclasses?
class Parent {
public void first() {};
public void second() {};
public void third() {};
}
class Child extends Parent {
@Override
public void third() {}; //change implementation of third function, reusing the first two.
} module Parent {
let first = () => ();
let second = () => ();
let third = () => ();
};
module Child {
include Parent; //add parent funcs to namespace
//@Override
let third = () => ();
};
I make regular use of this pattern production. module Foo = struct
let first = 1
let second = 2
let third = 3
end
module Bar = struct
include Foo (* Include contents of [Foo] *)
let third = 4 (* Override [third] *)
end module Foo = struct
let first() = 1
let second() = first() + 1
end
module Bar = struct
include Foo
let first() = 0
end
Bar.second () will still be 2 because of static binding. Thus you cannot use this approach to replace 'first' by itself without creating inconsistencies. data Numberable = Numberable {
first :: IO ()
,second :: IO ()
,third :: IO ()
}
parent = Numberable {first = return (), second = return (), third = return ()}
child = parent { third = print 'third' }
And if you wanted to DI into a function: data Env = { numberable :: Numberable }
doStuff :: (MonadIO m, MonadReader Env m) => Int -> Int -> m ()
doStuff num1 num2 = do
myNumberable <- reader numberable
print (show num1)
print (show num2)
liftIO (third myNumberable)