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

Traditional programming languages and imperative thinking don't lend themselves to writing state machines, so its not really that surprising that they're under utilized.

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.




>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

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?


Heh, very often their problem domain is also an issue.

"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?


Haskell code for that looks quite nice as well - however, it's less about a language per se but rather about availability of libraries and how mature / well-built their API is.

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.


> It's less about a language per se but rather about availability of libraries and how mature / well-built their API is.

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.


I agree. For me what matters most is language implementation (compiler/VM quality, GC quality, etc) and important libraries (and whether they are good). Language itself is not very important. I can write boilerplate, but I can't write GC implementation. So while I don't like Go language, for example, its implementation is very good and I can live with it.


> Haskell code for that looks quite nice as well - however, it's less about a language per se but rather about availability of libraries and how mature / well-built their API is.

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.



you forgot the "oh and requirements will change randomly as you're getting employee record from xml file to etc etc


In my experience, that's really not an argument against Haskell. I find it easier to make large changes in my representation of the world in Haskell than in any other language I've worked in.


As much as I love haskell and want to say I've had those same experiences, that hasn't been my experience. Haskell forces me to write better code so often that it's painful when bad code will do just as fine.

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


Well, despite what we tell ourselves, I think that most code we write is actually short lived. As in, it is only used for a short time. It might be in a zombie state for many years and even be revived, if it's an Open Source project, but that's not the common scenario.

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 agree with most of that, but I find that when my code is changing drastically is when I get the most help from my type checking, and find it most conspicuously absent when I use "less strict" languages.

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.


well said thanks! probably what i might have said if i had more eloquent wording :D


> 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.

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.


+1 F#, really nice language


FWIW, I came to Haskell by way of OCaml, and it seems to have gone well.


What's worked for me is using Scala on real production projects and just taking it slow. First year or two I was writing Scala that looked like Java, last year or two I've been writing Scala that looks like Haskell, but because the language supports both styles I was able to learn one piece at a time and stay productive the whole time.


I don't think 'three haskell tutorials' is ever enough to teach you a completely new programming language/paradigm. You wouldn't learn C in 'three C tutorials' either, would you?

Perhaps a Haskell book with a project or two would be a better alternative?


No, but if well done, it could be enough for me to say, "I get why this is worth pursuing further." I've had the same experience as the person above: Haskell tutorials seem to say, "Look what I can do!" and not, "See how you can do this?"


Well, after a few tutorials you should have noticed that it's a high-level language with clean syntax and a compiler that produces relatively fast binaries. That's a start. What else were you expecting?


Something that shows me how this is worth spending the time learning, when I could just as easily use another high-level language with clean syntax and a compiler that produces relatively fast binaries - but that are not functional - minus the learning curve.


Well shit. I guess teaching languages designed by academicians aren't for you. Same goes for blog posts written by random amateurs on the internet. A whole three tutorials, too! You should ask for a refund.


I didn’t expect to ‘learn Haskell’, but learning anything at all about how the actual code being presented worked would have been nice.


I find OCaml is a much more accessible language for getting your head around functional paradigms.


I'm following along with Learn You A Haskell[0] and it's the only Haskell tutorial I've found that's enjoyable to read and is super easy to follow and understand. I definitely recommend it.

[0]: http://learnyouahaskell.com/


Yes, agreed.

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.


Currently just started myself on http://haskellbook.com/, their philosophy seems to be just something for you, teaching functional programming with haskell from well defined fundamentals to make sure everything clicks. If they deliver on the promise I am yet to find out!


The erlang tutorial is pretty effective at that, IMO. The biggest problem with it is that erlang syntax is so foreign to most programmers you're going to spend enough mental effort understanding that to detract from the brainpower available for understanding the functional paradigms.


I found the opposite to be true. It's so 'foreign' that it avoids me falling into "I already know what this does" traps. Except for 'if'. Avoid 'if'.


Isn't that why Elixir came about, to be Erlang with a less esoteric interface?


Sure, but does Elixir have the exact same tutorial?


> Traditional programming languages and imperative thinking don't lend themselves to writing state machines

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.


> (particularly the "go back" one).

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...........


That's also why state machines are common in GUI frameworks, as noted by a sibling comment above.


> State machines are super commonly used in languages where you can (easily) construct ADTs and pattern match on them.

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?


Github?


Unfortunately no -- NDA / work-for-hire. Customer requested .NET but didn't care which language. We usually write Python, F# felt friendlier than C#. State classes looked like:

    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.


Plenty of imperative domain spaces use state machines, gamedev and the like come to mind in particular.


Similarly with embedded development. We use them for just about everything from communications to scheduling. I think the subtext here is that state machines are just rarely used for web/mobile...


Yup, I'm in the middle of writing a packet radio protocol and it's mostly just nested state machines.


One simplistic state machine in web/mobile is mouse/swipe motion handling – mousedown transitions into "in motion" state, mousemove tracks that state, mouseup transitions into "finished motion" state, runs event handlers, and transitions again into "idle" state.


Definitely true for gamedev in my experience. I don't think I've worked in a game code base of nontrivial size without seeing some implementation of state machines.


The "some implementation" probably is part of the problem - if there was a good generic implementation included in the standard library so that it could and would be used in language tutorials (especially in languages where rolling nice state machine code is tricky), then developers would use them much more.


The problem with that is each system has slightly different requirements. Scripting state machines vs animation state machines are going to have very different constraints and end-goals.

[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


What? No, that isn’t true at all. State machines come before the FP/IP divide even existed.

State machines are also intrinsically stateful, that should be obvious.


The argument is not that state machines are the child of FP, just that a common idiom in FP, Pattern Matching over ADTs, makes them easy to implement.


This might be, but state machines are so common in imperative code, you could say they are common idiom there also. Pattern matching over ADTs only drives transitions; different representation of transitions can lead to different constructs being more convenient (e.g. if your transitions are just based on a finite set of values, you can use just dictionaries).


That could very well be. My brain tends to map problems to ADTs with very low friction.


> State machines are also intrinsically stateful, that should be obvious.

So are lots of data types, but those are still useful in FP.


Yes, that should be obvious also. State machines have no strong relationship with FP. I'm not sure where this claim even comes from!


This comment reminds me of something I read recently on Yaron Minsky's twitter:

"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)


In 's4vi0r’s defense, “FP” usually means ML-style FP, which does happen to be pretty biased towards creating stack-based FSMs since it has literal syntax for stacks (list literals), states (discriminated unions + tuples), and transitions (pattern matching).


>“FP” usually means ML-style FP

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.


Traditional programming languages and imperative thinking don't lend themselves to writing state machines.

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.


State machines are still and by far most commonly used in C, where, lo and behold, most low-level and embedded programming is still done.

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.


> And function pointers make up for pretty much the only fundamentally useful aspect of FPs regarding FSMs which is functions as first-class objects.

I'd argue sums and pattern matching are almost as important given the simplicity of expression.


State machines are one of the most traditional programming constructs there is, and most people I've seen champion or use them are the types who would rather program in assembly than Haskell. Heck, some "imperative thinking" programmers consider state machines only slightly more exotic than a for loop, and would be similarly dismayed if a colleague didn't know how to write one.


I don't think there is a conflict between imperative thinking and state machines, but I do agree that lots of programming languages neither provide built-in features for expressing state machines nor support expressing them particularly elegantly, and that the superior support for general abstraction in certain functional languages reduce the friction of use.

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.)


> Traditional programming languages and imperative thinking don't lend themselves to writing state machines,

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.


> 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"

many of "the older FP guys" actually think "it's cool, it's mathematical. But it's not practical."


As a whole, a database-backed CGI server can be considered a state machine.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

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

Search: