Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

So I have very limited experience with FP, and a reasonable amount with OO (mostly dynamically typed).

I can really see the benefits of FP, but there are some problems I have trouble modelling with FP.

For instance, if I have a simple 2D rendering engine, I just want to say "add this object to the screen". The object might be a geometric primitive (square, circle, etc.), it might be generated particles, or it might be an image or video or something. The way I deal with this at the moment is have Drawable or something to add to the screen with something like, which implements an interface with a "draw" method.

    screen.addToScene(new Circle(...))
    screen.addToScene(new Square(...))
    screen.addToScene(new ParticleGenerator(...))
    screen.addToScene(new ImageSprite(...))
Then the game would loop over each of the Drawables, then call .draw() on them, which is implemented differently for everything that implements Drawable.

How would I model this in FP?

The only solution I can think of at the moment is to have a draw function that does pattern matching on the type of thing and do it that way. How do people do stuff like this in scheme or other languages with limited support for pattern matching?

The problem I have with this is that it means every time I want to add a new kind of thing, if it implements many methods in an interface, I have to go to many different files to implement how this new kind of thing works.

Among other things, that's a huge pain for revision control, since if I have 3 coworkers adding new kinds of things that can be drawn, we're all going to have to modify the draw function. In OO, we'd each just be creating a new subclass in its own new isolated file.

As a second question - what should I read to get a good idea of how to sanely model things in OO and FP? I've read a lot of debate about the right way of doing things, but I don't really know where to learn this stuff. The OO class in university was completely useless, since the examples were outrageously contrived and too small to see any real benefits. I'd ideally be looking for 1 book that explains how to model real problems in OO very clearly, and one book for how to model real problems in FP.



I encourage you to read Philip Wadler's essay The Expression Problem, which addressed precisely the dilemma you point out:

http://www.daimi.au.dk/~madst/tool/papers/expression.txt

In brief, if you think of data types are rows, and behaviors as columns, the question is how to extend either the rows or the columns naturally.

In your example, it is easy to add a new row (datatype) – create a Triangle class which implements the Drawable interface. It is difficult to add a new column (behavior) – if you realize all of these datatypes should also have a "extrude to additional dimension" behavior, you're going to have to individually implement that in all of your different classes, across many different files, etc. All of the problems that you note arise when adding a new datatype in the FP strawman.

It's important to recognize that this is indeed a difficult problem, and that addressing it well takes real care.

The c2 wiki has a good distillation:

http://c2.com/cgi/wiki?ExpressionProblem

and this paper (by the Scala people) is very nice:

http://www.scala-lang.org/docu/files/IC_TECH_REPORT_200433.p...

Some approaches that languages take, to varying degrees of success, include typeclasses in Haskell, multimethods in Clojure and elsewhere, the Visitor or Extended Visitor patterns in OO languages, controllable extensions in C#, Ruby, and Scala, etc.


Thanks for the sources - will sit down and read them later.

The row, column analogy is pretty apt - it's an interesting way of looking at things.

While it is true that adding a new behaviour in OOP is a pain in the ass, I definitely find myself adding new datatypes far more frequently than adding new behaviours for an interface.

Isn't adding a lot of new behaviours to data typically a sign than the interface is bloated and is now dealing with too many things?


To attach behaviour to data in a functional language, you typically use first-class functions. Your draw function would look for a function in each drawable object and call it.

To your second question: find some great open source projects and read their code.


The problem with open source projects is that great != popular.

There are certainly a lot of very successful projects that have painfully unmaintainable code that still get maintained because so many people are invested.

And the problem with great open source projects is that they'll only show you how they did their problem right - but seeing how to do it wrong and _why_ it's wrong is typically a more useful process.

I think it's generally easier to avoid doing bad things you understand the problem with than try to write excellent code by blindly following patterns that you assume are good because someone well known uses them.


Excellent points. I'm doing a lot of code reading myself these days so it's nice to be reminded of some of the risks. :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: