Hacker News new | ask | show | jobs
by Twisol 1961 days ago
The code you've selected is not "for circles", per se. This is classic double-dispatch -- the function itself represents a circle (via the `x, y, r` values it closes over), and it chooses which receiver to invoke based on its identity. (The parameters in the selected function may be better named `onCircle` and `onRectangle`.)

If you just have a Shape, and you need to do something specific depending on the kind of Shape you have, you need some way to tell what kind of Shape you have. You can use `instanceof` and casting, but there's no guarantee that you've handled all cases(^). Moreover, it's painful in some languages (like Java) to extract the subclass-specific fields, as you need to rebind the value to a new variable of the right type first.

The Visitor pattern is a classic object-oriented solution to this problem, typically using double dispatch. The Shape itself knows what kind of shape it is, so rather than asking it what type it is, you provide it a set of _strategies_ (no relation to the Strategy pattern), one for each type of Shape. The Shape doesn't know what you want to do with it, so it calls you right back, invoking the circle- or rectangle-specific logic depending on what kind of shape it is. (Hence, double-dispatch.)

Gabriel (OP) observes that the Visitor pattern is exactly the Boehm-Berarducci encoding of a sum type. The Visitor pattern is very common in OO programming (see, for instance, abstract syntax trees), so the fact that we're so often using an encoding of a more direct concept is worth remarking on. I know I'd much rather use sum types in general than use the Visitor pattern.

(^) As an aside, I've never found "Shape" to be a very convincing example of sum types, as it's much easier to imagine as an open family than as a closed family. In an open family of shapes, there is no "all cases", and instanceof/casting is inappropriate from the beginning. I think object algebras (see my other comment) give a more motivating class of examples of closed families, including ASTs.

1 comments

I would like to support your comment and add that I enjoy these articles because I like programming languages and thinking about program execution.

However, I think what delibes is getting at is that this is article exhibits a classic trigger for most developers because it starts with naming some language (i.e. Haskell) and then it is filled with assertions that are always "What If": what if your language doesn't support sum types or recursion or algebraic data types or ... Most devs are looking for practical applications for their language of choice so there is a natural inclination toward a critical comparison of "their" language and "my" language.

But we should follow Twisol here and not read this article as "language X is better than language Y" or, more precisely, "throw out unnecessary features from language X because you can still perform some task Z".

Just take the article for what it is: a great "explanation"[1] of the relation between mathematical foundations and language features or characteristics. This article isn't some heretical tantrum so just sit back and enjoy the learning.

[1] https://documentation.divio.com/

I have noticed a lot of random hate against Haskell devs specifically, see https://twitter.com/catachresthetic/status/13106325659556044... for another example.