[Haskell-cafe] Client-extensible heterogeneous types
Jacek Generowicz
jacek.generowicz at cern.ch
Wed Oct 13 17:18:29 EDT 2010
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?
More information about the Haskell-Cafe
mailing list