I wonder how much of the "small, composable functions" nature of FP can be attributed to the types of programs you write in functional languages, and the types that you don't.
Unix-like tools such as grep (or ghc) are very much like pure functions: programs that accept input, and produce an output data. It's not surprising that they lend themselves well to FP techniques. But other programs, like the web browser I'm using now, have lots of "inputs" and "outputs." There's many knobs that can be turned, and output goes to screen, disk, network, other programs...
I suspect these programs have a larger essential "hairiness." grep only has to search text. But Find in a text editor has to show a progress bar, cancel button, intermediate result count, etc. These features are intimately intertwined with the algorithm itself, and that's often hard in FP. Try writing a Haskell function that does text find/replace with live progress reporting. It's not easy, and it ends up looking a bit like Java.
Note that the land of unix-like coding isn't very good at UIs either!
I'm finding that FP tends to shave the "hairiness" off things, many times in ways I had not anticipated.
UIs are a completely different animal. I've done a lot of UI stuff in the OO world in the past, and some in C/C++. The couple of apps I wrote in F#? I ended up doing a kind of functional-reactive thing. I really like the FRP paradigm for UI work, but I need a lot more experience to say anything useful about it. One of the things I started doing was setting up derived types from Win32 objects. Looking back, with that kind of attitude I was probably headed down the wrong road.
A web browser, eh? that's very interesting. One of my projects does some screen scraping. I found that scraping could be done in a pipeline -- get the page, score the sections, run some rules, do some QA, etc. Each stage did some work and left things for the next stage. But, of course, I was processing many pages at the same time. Rendering one page for a user sitting in front of a screen is a completely different scenario. I think.
> I suspect these programs have a larger essential "hairiness." grep only has to search text. But Find in a text editor has to show a progress bar, cancel button, intermediate result count, etc. These features are intimately intertwined with the algorithm itself, and that's often hard in FP. Try writing a Haskell function that does text find/replace with live progress reporting. It's not easy, and it ends up looking a bit like Java.
Ah, I suspect you're not familiar with things like conduits/pipes/iteratees/etc. These allow you to express and compose those kinds of dirty things that you're looking for--incremental input/output, progress reporting, etc. So you could write a text search function, compose it with a progress reporter that reports how quickly it traverses input, and then report the output progressively, and dispose the whole thing at any time. Haskell's type system is fairly awesome at letting you do things like this, enough that people are still discovering neat tricks decades later.
Unix-like tools such as grep (or ghc) are very much like pure functions: programs that accept input, and produce an output data. It's not surprising that they lend themselves well to FP techniques. But other programs, like the web browser I'm using now, have lots of "inputs" and "outputs." There's many knobs that can be turned, and output goes to screen, disk, network, other programs...
I suspect these programs have a larger essential "hairiness." grep only has to search text. But Find in a text editor has to show a progress bar, cancel button, intermediate result count, etc. These features are intimately intertwined with the algorithm itself, and that's often hard in FP. Try writing a Haskell function that does text find/replace with live progress reporting. It's not easy, and it ends up looking a bit like Java.
Note that the land of unix-like coding isn't very good at UIs either!