
On 2010 Oct 13, at 00:28, Alexander Solla wrote:
On Oct 12, 2010, at 4:24 AM, Jacek Generowicz wrote:
I can't see a Haskell solution which combines both of these orthogonal features without losing the benefits of the type system. (For example, I could create my own, weak, type system with tags to identify the type and maps to do the dispatch.)
Is there any particular reason why you want to actually to mirror Python code?
I don't want to: I merely have a situation in which an OO solution (not necessarily a good one) immediately springs to mind, while I didn't see any obvious way to do it in Haskell. (I am sure that this is my shortcoming, not Haskell's.) I included the Python example lest my question be too nebulous without it. I would be delighted to learn approaches which are completely different to anything offered by OO. In fact, for personal didactic purposes, being un-OO-like could even be considered to be a goal.
I think that letting the programmer design domain specific control structures is rather the point of Haskell.
While I don't, at the moment, understand exactly how this is the case, I do like the sound of it.
Instead of relying on a one-sized fits all solution (which only really fits one kind of problem), you write your own. And it is typically easier to write the control structure than it is to implement it using the OO patterns, because of the notion of irreducible complexity. For example, the Factory pattern constructs a functor. You can write the essential semantics of doing this with a single Functor instance, instead of writing multiple classes which implement the semantics, while relying on implicit, and possibly ill- fitting semantics of method dispatch. The other OO patterns make this objection stronger. If you can write a UML diagram, you can turn it into a commutative diagram, and write less code by implementing its arrows.
Lots of stuff that sounds fascinating, but whose detailed meaning is, at the moment, beyond my grasp. So let my start off by getting my teeth into your example code:
An OO class hierarchy is a very specific functor over objects (which attaches methods to objects).
This sounds very interesting, but, again, I'm having difficulty understanding *exactly* how that is.
Haskell provides the Functor type class. Write your generic functions for specific functors:
-- The varying "input" types. Will be attached to arbitrary values by the Functor instance.
data A = A -- Variant 1 data B = B -- Variant 2
-- Some normalized Output type. data Output = Output
-- The new control structure. data Attaches a = AttachesA A a | AttachesB B a
-- Stick your conditional (varying) semantics in here. Corresponds to heterogeneousProcessor.
Could you explain this a bit more? heterogeneousProcessor was extremely boring: its only interesting feature was the dot between "datum" and "method()" Here it is again: def heterogeneousProcessor(data): return [datum.method() for datum in data] I suspect that runAttaches is (potentially) a lot more interesting than that!
-- The output presumably depends on whether A or B is attached, so this function is not equivalent -- to something of the form fmap (f :: a -> Output) (attaches :: Attaches a)
runAttaches :: Attaches a -> Attaches Output runAttaches = undefined
-- This corresponds roughly to heterogeneousProcessor(heterogeneousContainer): processedOutputs :: [Attaches a] -> [(Attaches Output)] processedOutputs as = fmap runAttaches as
Would it be correct to say that runAttaches replaces Python's (Java's, C++'s etc.) dynamically dispatching dot, but also allows for a greater variety of behaviour? Alternatively, would it be interesting to compare and contrast runAttach to CLOS' generic functions, or even Clojure's arbitrary method selection mechanism?
-- Functor instance. Now you have a way to treat an (Attaches a) value just like you would an a. (modulo calling fmap) instance Functor Attaches where fmap f (AttachesA A a) = (AttachesA A (f a)) fmap f (AttachesB B a) = (AttachesB B (f a))
[ Aside: Briefly returning to my original question: I don't see how, if this were supplied in a library, it would allow clients to inject new entities into the framework. It all seems to hinge on the Attaches type, which would be defined in the library, and is not extensible without modifying the library source code (unless I'm missing something). Which doesn't diminish my desire to understand what you are saying, in the slightest. Can the set of variants usable in this framework be extended without modifying the original source? ] Coming back to your statement that "An OO class hierarchy is a very specific functor over objects (which attaches methods to objects)", how would we complete your code so that it implements this particular functor?