I've not been ignoring them. I tried at least three different Haskell tutorials and articles explaining how cool it is. The problem was the author would show some code sand say 'see how easy it is to do this, and this, and this!', but I'd look at the code and have no idea whatever what it was doing or how it was doing it, and the guide/tutorial wouldn't tell me. After a few tries, I just gave up.
Maybe there's a canonical newbie's tutorial that takes you through the shift from imperative/procedural thinking?
"We're going to write a compiler in our shiny FP language".
"We're going to implement a Fourier transform".
Nah, thanks, could you show me instead how I can get the Employee record from an XML file, stick it in a PostgreSQL database and also send it down the wire through a REST API as JSON?
For quite a few FP languages the ecosystem is there and you can do all these problem domains nicely, they just tend to be skipped in tutorials as they rely on non-core third party libraries (sometimes with multiple nice but very different alternatives). Perhaps a "batteries-included" stance of Ruby(+Rails) and Python would simplify that, but it's more of a political issue.
In the real world, those matter just as much as the language. They usually matter even more :)
Look at what Rust is doing - I think at least half of their effort is spent towards building up a large collection of high quality, well maintained (i.e. feature requests implemented, bugs fixed quickly) and well documented libraries.
That might be the case, but you simply never see tutorials for writing a CRUD-like web application in Haskell. Maybe they exist, but they don't seem to show up very often here or on reddit or whatever.
I'm always surprised how often bad code is the solution too.. And when I say the solution, I mean to all the points along the path that I may take to get to the final destination. And I'm not saying this because you can't write this type of code in haskell but because haskell makes it more difficult and that's not always a good thing
As a result, if most of the code written by most programmers is short lived and during that short life changes drastically, super-strict languages actually slow you down a lot.
The real problem is: sometimes certain parts of our code live very long and intense lives. But we never know which parts and at which moments. If we knew, we'd just write those parts in Rust/Haskell and the rest in Javascript or Visual Basic and live merrily ever after.
To paraphrase P.T. Barnum: I know that 10% of my code needs to be extremely fast, easy to refactor and readable, I just don't know which 10% :D
I've no doubt this depends on context, on habits and approach, on skill with the languages in question, and on skill with effectively using static typing in general, so I'm not surprised that others' experiences differ.
You're better off learning OCaml or F# for a small project or two, honestly. The jump from pure procedural to pure functional is big enough without also dragging in laziness, type classes, and monads.
Perhaps a Haskell book with a project or two would be a better alternative?
There's the shift to functional thinking, which should not be underestimated. Next up is learning the target language syntax. Then there is the issue of gaining familiarity with the tools & libraries available.
That's probably not the problem - imperative development can start off from a level of complexity where state machines don't look relevant.
Six weeks down the line, the whole codebase has overtaken the complexity of a state machine, though each of the development bugs were simple fixes to the original branching code.
The standard web-app wizard is where I've run into this again and again.
Every web-app is stateful enough to maintain DB state sync'd & ticking over from a user-click, which makes it really easy to work out whether all clicks go somewhere useful.
However this makes sense only when you have around 7+ states and transitions between them (particularly the "go back" one).
Until then, the regular if/else branch scenarios work out just fine ... but then when you're near the 20-30 state range, it all falls apart.
Holy shit, once I built a web app for some biologists that wanted a "designer wizard." First I implemented a really shitty buggy wizard. Then I refactored it all into a state machine...........
I had the opportunity to use F# for the first time last month, and I experienced this first hand -- it was far easier to write a procedure as a sum type with transition functions than it would have been to write it procedurally. And with all the advantages of having the states of the system and their transitions laid out explicitly, why fight it?
type InitialState = {a : int; b : string}
type IntermediateState = {a : int; b: string; c: string list}
type FinishedState = {a: int; b: string}
type ErrorState = {a: int; b: string; message: string}
type State =
| UninitializedState
| InitialState of InitialState
| IntermediateState of IntermediateState
| FinishedState of FinishedState
| ErrorState of ErrorState
| FinalState
And transition functions: let initialize (args : string list) (s:UninitializedState) : State =
// create an initial state from args, not actually like this
InitialState {a= 5; b="hello"}
I probably put too many types into my function signatures, but I'm new to this style.[edit]
For example here is UE3's anim tree[1] editor vs Kismet[2].
[1] https://docs.unrealengine.com/udk/Three/AnimTreeEditorUserGu...
[2] https://docs.unrealengine.com/udk/Three/KismetUserGuide.html
State machines are also intrinsically stateful, that should be obvious.
So are lots of data types, but those are still useful in FP.
"An odd habit of functional programmers: when confronted with a nice, but clearly imperative way of structuring a program, they will often declare that this technique is in fact functional." (https://twitter.com/yminsky/status/950883335324225541)
and then
"Case in point: structuring a program as an imperative, deterministic state machine, where the state is determined fully by the state machine logic plus the sequence of transactions." (https://twitter.com/yminsky/status/950883598189686784)
Only after sometime around 2010. Before that it was mostly Lisp and Scheme. Sometime around then, the trend around Haskell, purity, and co overtook them as what people mean when they talk about FP.
Linden Scripting Language, used for Second Life, has explicit state machines as a first-class programming construct. Programs are divided into state sections, using a keyword "state". Each state has its own local functions.
And function pointers make up for pretty much the only fundamentally useful aspect of FPs regarding FSMs which is functions as first-class objects.
Everything else pretty much just substitutes one convenience for another. A pretty good case can be made about how the State Pattern makes traditional OOP indispensable in FSM design, and I'm sure that in OO languages with functions as first class objects (like Python, Lua or Javascript) people can showcase elegant designs that to them far surpass both classically OO or classically FP designs etc. etc.
I'd argue sums and pattern matching are almost as important given the simplicity of expression.
It's pretty easy to imagine, though, a class based OOP language where each class was also an HSM, with methods defined per state and identifying transitions (as well as states and their entry and exit behavior being explicitly defined.)
pretty sure most C introduction books cover various implementations of state machines. In "traditional" desktop WIMP GUI software it's a fairly common paradgim ; a bunch of frameworks such as StateCharts with SCXML even allow you to design the state machine graphically and have it compiled to C++ or Java code.
many of "the older FP guys" actually think "it's cool, it's mathematical. But it's not practical."
Its kind of frustrating constantly reading posts where people shit on functional programm(ers|ing) for being too ivory tower-y or whatever, when its kind of hard not to be when a lot of the older FP guys have spent the last like 20-30 years going "yo this is dope you guys should really be doing this" and getting largely ignored. State machines are super commonly used in languages where you can (easily) construct ADTs and pattern match on them.