3 ms·
> Haskell’s typeclasses and OCaml modules solve this problem neatly. Neither do, really. Imagine you have an existing typeclass with three functions. How do y
by hota_mazi 7y ago
> Haskell’s typeclasses and OCaml modules solve this problem neatly.
Neither do, really.
Imagine you have an existing typeclass with three functions. How do you create your own typeclass that reuses two of these three functions but your own instance reimplements the third one?
Try it. It's pretty much impossible, or at least not without a lot of boilerplate and forwarding.
- xyzzyz 7y agoNot sure what you mean, exactly. Could you sketch a simple example with some types and typeclasses?
- callmeal 7y agoThis is how it would be done in Java: 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. }
- mrkeen 7y agothird = first + second
- Hermitian909 7y agoI would accomplish this in modules in the following way. I use reasonML syntax but it's OCaml under the hood 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.
- andrepd 7y agoIn OCaml: 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
- deleted 7y ago[deleted]
- colllectorof 7y agoOCaml has real objects and classes. Moreover, it is trivial to demonstrate that your example doesn't work in practice: 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.
- wowthisanacct 7y agodata 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)
- inimino 7y agoDo you mean your own instance of a typeclass? Because that's the direct Haskell analogy to a subclass in Java. I'm not sure where the difficulty is here, as what you're describing is quite straightforward. You can also have the same type be an instance of as many typeclasses as you want, which is something that inheritance-based subclassing and tree hierarchies (is-a rather than has-a) has always made awkward. > Reuse 90% of this piece of code but alter just this 10% There is no general solution to this, in any programming language, without some foresight (unless you admit some crazy features like arbitrary code re-writing or source-level patches). If you have, say, a single function of 100 lines, and 10 lines need to be changed, you're going to have to edit that code to enable the change, and if that 100 lines is in a third-party library or code you otherwise don't control, you're going to have a hard time. However, if you control the code and are able to make changes to it to support new behaviors, FP languages give you plenty of power here, just as OOP languages do. There's not a lot of objective difference here in power and plenty of differences in taste and familiarity, so please be careful about repeating "you can't do X in language Y".