| > React begs to differ. React is good for certain classes of UI, granted. I use another FRP-style library (not React) to render UI in my current game, and it works well -- except that it doesn't mesh well with me trying to control it from an OO game, but I've created an interface that works. But imagine creating Adobe Photoshop, Maya, or Microsoft Word entirely in React, and tell me again that FP would be the ideal choice. For any particular dialog that pops up? Absolutely. For the entire app? You'd end up with a "god object" that would make the app unmaintainable. OO gives you compartmentalization that you don't get with FP. FP is great for problems up to a certain complexity. After that it falls apart. Thing is, 98% of apps don't come close to that level of complexity, so there are lots of people who never even work on an app that won't work well with FP. In the RectIterable example you gave, I'm afraid I don't know enough Haskell to comment on it intelligently. Is "instance" adding an interface to TileMap/HexMap so that either can be passed in as a parameter that requires a RectIterable? Can other interfaces be added that way to TileMap/HexMap? In my editor, can I say something like myTileMap.iterateRect after doing this, or do I need to know that iterateRect exists and remember exactly what it's called? The last point is salient: Discoverability is a huge part of the UI of a programming language, and memorizing all of the exact function names that are appropriate for a data structure is not fun. |
Well, not quite; take a look at the Elm architecture [0]. It's basically what Redux gives you, but more explicit.
The idea is, that yes, while you have a god object in the top-most component, child components don't know anything about it; they operate on their piece of state completely independently. This makes UI elements perfectly composable and reusable, since in the end, a UI element is just a pure function and nothing more.
Not to mention other nice side-effects (sorry :)) of pure UI architectures, like time-travelling debugging, sane logging and so on.
> FP is great for problems up to a certain complexity. After that it falls apart.
I disagree completely. FP, and moreover pure FP, is especially well suited for complex problems. Pure functions are testable (if you haven't heard of QuickCheck / generative testing, you've missed out) and as I said above, composable.
If anything, I've never seen a big OO program made out of truly reusable components. Because classes and methods are often impure, before calling a method one must make sure that the correct environment is set up in the right way (if you've ever forgotten calling initSubsystem() before subsytemDoSomething() you know what I mean).
One can rip out a pure function from one codebase and reuse it, as-is, no modification necessary, in another one without any problems. How often does this happen in a big OO project?
> Is "instance" adding an interface to TileMap/HexMap so that either can be passed in as a parameter that requires a RectIterable? Can other interfaces be added that way to TileMap/HexMap?
Yes, and yes. In Java, when you have a class like this:
in some library, you can't add D to the list of implemented interfaces.In Haskell, you can:
Haskell assumes an "open world" - i.e. everybody can add instances to a data type even after it has been defined already.I can't give you a complete overview of the differences between ad-hoc and parametric polymorphism, but there are plenty of resources online if you are interested.
> In my editor, can I say something like myTileMap.iterateRect after doing this, or do I need to know that iterateRect exists and remember exactly what it's called?
I can only speak for Haskell here. It's a static language, so things like autocompletion, show type at cursor, jump to definition etc are not a problem. The tooling could be a whole lot better, no doubt, but it's not bad. The REPL helps a lot, too.
[0] https://guide.elm-lang.org/architecture/