3 ms·
That's indeed the right pattern to use in OO. However, OO isn't necessarily the most concise approach to such problems :-) data Node = Elephant | Box [Node
by cousin_it 12y ago
That's indeed the right pattern to use in OO. However, OO isn't necessarily the most concise approach to such problems :-)
data Node = Elephant | Box [Node]
count Elephant = 1
count (Box nodes) = sum (map count nodes)
- innguest 12y agoThis is many times more readable, simpler and safer than what Martin Fowler wrote. I wonder if he will ever grow out of the OO hypnosis. Maybe he just carved too comfortable a niche for himself that he needs to keep peddling it. I say this becaue I think it is harmful that he uses his fame to keep outdated programming techniques around, contributing to overtimes, bugs galore, and loss of productivity.
- djur 12y agoIt's easy to golf a more concise solution to a contrived example like that, yes. The Haskell implementation starts to get more complicated when you want to be able to define additional participants in the role of 'Node' without the original implementation having to know the name or structure of those participants. That's extremely common in game programming, for example.
- cousin_it 12y agoWell, if the additional participants only need to support the "count" operation, then you can do without tree-shaped data types at all, and just use a single Integer for the whole thing. After all, a single lazy Integer in Haskell is already an unevaluated tree of computations, there's no need to build additional trees out of it :-) Also this way you get memoization for free. If we need to support other operations as well, Haskell is perfectly capable of expressing the usual extensible OO solution, by using a record of functions. (A record type containing functions in FP is basically the same as an interface type in OO, and instances of that record type correspond to implementations of the interface.)
- djur 12y agoA record of functions permits polymorphism in behavior, but I'm not clear on how it can provide polymorphism in state or structure. I'm certainly no expert in pure FP so there may be something I'm missing, but if the operations have to produce a change in the state of an entity, each one of the functions would have to both receive and return a state, right? Or you use a record of closures, each which returns a new record of closures? It seems to me that in both cases you're discarding a lot of the benefits of Haskell's type system.
- cousin_it 12y agoFor what it's worth, I agree that a graph of stateful objects referencing each other is much easier to express in an OO language than in a pure functional language. There are many functional solutions, but none of them are very nice IMO. Maybe that's one reason to use an impure functional language like ML, which I consider an overall better language than Haskell.
- djur 12y agoI think we agree on this one. I've really been enjoying using OCaml exactly because I can make use of mutable state or OO-style polymorphism when I want, but otherwise it feels very natural to write pure functional code. All I need to do is wrap my head around functors and first-class modules and I'll actually feel like I understand it well enough to use it for real work.