<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Oct 12, 2010, at 4:24 AM, Jacek Generowicz wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; font-size: medium; ">I can't see a Haskell solution which combines both of these orthogonal<br>features without losing the benefits of the type system. (For example,<br>I could create my own, weak, type system with tags to identify the<br>type and maps to do the dispatch.)</span></blockquote></div><br><div>Is there any particular reason why you want to actually to mirror Python code? I think that letting the programmer design domain specific control structures is rather the point of Haskell. 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.</div><div><br></div><div>An OO class hierarchy is a very specific functor over objects (which attaches methods to objects). Haskell provides the Functor type class. Write your generic functions for specific functors:</div><div><br></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">-- The varying "input" types. Will be attached to arbitrary values by the Functor instance.</font></div><div><span class="Apple-style-span" style="font-family: Courier; "><br></span></div><div><font class="Apple-style-span" face="Courier"></font><span class="Apple-style-span" style="font-family: Courier; ">data A = A<span class="Apple-tab-span" style="white-space:pre">        </span>-- Variant 1</span></div><div><font class="Apple-style-span" face="Courier">data B = B<span class="Apple-tab-span" style="white-space:pre">        </span>-- Variant 2</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">-- Some normalized Output type.</font></div><div><font class="Apple-style-span" face="Courier">data Output = Output</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">-- The new control structure. </font></div><div><font class="Apple-style-span" face="Courier">data Attaches a = AttachesA A a</font></div><div><font class="Apple-style-span" face="Courier"> | AttachesB B a</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">-- Stick your conditional (varying) semantics in here. Corresponds to heterogeneousProcessor. </font></div><div><font class="Apple-style-span" face="Courier">-- The output presumably depends on whether A or B is attached, so this function is not equivalent </font></div><div><font class="Apple-style-span" face="Courier">-- to something of the form fmap (f :: a -> Output) (attaches :: Attaches a) </font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">runAttaches :: Attaches a -> Attaches Output</font></div><div><font class="Apple-style-span" face="Courier">runAttaches = undefined</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">-- This corresponds roughly to heterogeneousProcessor(heterogeneousContainer):</font></div><div><font class="Apple-style-span" face="Courier">processedOutputs :: [Attaches a] -> [(Attaches Output)]</font></div><div><font class="Apple-style-span" face="Courier">processedOutputs as = fmap runAttaches as</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">-- Functor instance. Now you have a way to treat an (Attaches a) value just like you would an a. (modulo calling fmap)</font></div><div><font class="Apple-style-span" face="Courier">instance Functor Attaches where</font></div><div><font class="Apple-style-span" face="Courier"> fmap f (AttachesA A a) = (AttachesA A (f a))</font></div><div><font class="Apple-style-span" face="Courier"> fmap f (AttachesB B a) = (AttachesB B (f a))</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><br></div></body></html>