Factorio is a is queuing systems simulator. Just like your web server, those little factories process resources (requests) at certain speeds and pass them down to a bunch of other queuing systems (databases). I think it's really good at teaching intuition about queuing systems.
Yep that’s how I see it. The belts are Kafka, factories are microservices, etc. You have to manage backpressure, throughput, scaling and such just like that kind of environment.
I actually used to build all my factories around a huge central belt, until I first designed a few microservices for a toy project. Then I found myself splitting components into separate pods, using trains and logic circuits to manage their independent resource needs. Nothing deliberate, just my mind following the path of least resistance. Factory after that, it was back to the main belt.
You need to explore around. There are very rich fields far away from your base. You need to setup outpost with train delivery and that'll allow to run for a very long time before those fields will expire. And then with bots it's just a matter of copy-paste new base and connect it to your railway system.
I usually up resource richness at map creation, so that the fields last longer. I I think it doesn't take away from the game, because the size of the fields is still limiting, so there's need for exploration.
I find myself building a main belt almost immediately, pretty much right after getting a basic factory down. Really it's because my first base or two was just terrible spaghetti and when I was a new player I thought I could fix that by going with a central belt right off the bat. Since then I've loosened up much more, but I still like a central belt when I get the chance.
Unfortunately it’s nothing like supply chain management in reality! It’s a bit like automated warehouse design but not really (Supply chain & logistics consultant here).
What are some of the misconceptions that make it so different? "I need iron plates but there aren't any available" just feels so intuitively like a supply chain problem, I'd love to learn how the real world is so much more complicated.
They can be - but in the context of the game; they only ever are at the advanced level of gameplay. In general people aren't all running excel analysis on their factorio playthroughs (although I guarantee someone does).
I think the analogy for the entropy introduced by a "market" is just the player's attention span and long-term planning skills. In a beginner-intermediate session, the player can and will have highly variable production rates due to an inability to grok the complexity of what they have built. It's of course very similar to programming in that way.
I agree that the game is not trying to be a market simulator however.
> What are some of the misconceptions that make it so different? "I need iron plates but there aren't any available" just feels so intuitively like a supply chain problem, I'd love to learn how the real world is so much more complicated.
It's definitely a supply chain problem, but the way it is solved in Factorio (i.e. build a mine and a conveyor belt) is different to the way it is solved in reality (create a spec for the iron plate, a procurement process, contract negotiations, raising purchase orders, organising freight, managing compliance, all of which may be split across different teams). Then the iron plate company probably has the same thing to do for the iron - they probably don't own the mines where the iron ore comes from, so they also have to procure, contract, raise PO's, organise freight e.t.c.
So in reality, SCM is usually more about managing all those relationships and contracts rather than getting involved in end-to-end optimisation (which is sometimes done, but the details are the responsibility of another company - i.e. if a car company needs more bolts, they don't get involved in considering where a mine needs to be opened).
Yes. If supply chain management was just efficiency and forecasting, it wouldn’t be it’s own giant department in many manufacturing organizations.
There is an entire contracts negotiation side to it. Which is really fuzzy and filled with all sorts of intentional inefficiencies (price-wise) brought about by competing interests and incentives.
I would agree, although typically the companies, technologies and people involved in automated warehouse design are different to those doing production systems engineering.
(e.g. automated production has a bigger focus on cells, robotics and in-line production, while logistics automation is often more about automated storage and retrieval systems, sortation, piece-picking systems etc).
Very neat article. Since I got into and out of Haskell a while back, one of the complaints I always had about breaking into the space was that it was too abstract. Some of the core concepts of FP seemed really arbitrary when described without useful examples. So it's nice that the author has found a great analogy in Factorio.
However, I have to say that I don't think the author succeeded in showing me "that real engineering is functional." During my tour of FP, I would always eventually run into a wall of abstraction as soon as things got more than a little bit complicated. In that sense, Factorio comes across as a bit of a contrived example. As soon as you have an algorithm that lends itself to a few pieces of mutable state in a loop with complex terminating conditions, good luck. Yes, it's theoretically possible to shoehorn things like that into the formalities of FP. However, doing so usually ends up feeling like an academic exercise more than anything else. It doesn't feel like it moves you any closer to your ultimate goals; to implement functionality more quickly, cleanly, and intelligibly.
That being said, I don't regret getting into FP for a while. It's always a useful challenge to re-frame what you think you know with a different set of concepts. FP also works really well for certain kinds of problems. But I think the number of those are relatively few. This may be reaching, but I like to believe there's some historical precedent for this. After all, none other than Kurt Gödel himself eventually abandoned the λ-calculus in favor of Turing's mechanical (imperative) framing of computation. I want to believe there was some similar sentiment behind this decision. But who knows? It was probably more of a technical thing than I realize. But I've always felt on some level that an overabundance of abstraction necessarily means a lack of power.
If you are writing a complex algorithms then an imperative style is usually going to be clearer (and more performant), but when dealing with higher-level code that is just moving data around and doing some relatively straightforward mutations, then functional code can be much more straightforward and intelligible. When you introduce concurrency then that is where I think pure FP really shines. Writing concurrent code with a pure FP effect system like ZIO is so much nicer (and safer!) than writing concurrent code in Java (or any other language I've ever used).
ZIO (particularly with the V2 release just done) explicitly aims to be beginner friendly and accessible compared to other "pure" FP and effects libraries though
This isn't my experience trying to read documentation and tutorials with similar libraries in both Scala and Haskell
I would go so far as to say that ZIO is like the Python of the realm. It's practically oriented and beginner friendly first and foremost. Also Scala is easier to understand than Haskell, but that's an opinion.
Agreed, I think it's not so much that pure FP is too abstract and complicated. It can actually allow really clean, usable abstractions. It's just that many pure FP libraries for some reason try to explicitly model category theoretic abstractions so you end up needing a lot of theory to be able to get your bearings. ZIO is built on the same theoretical foundations but is designed so that you don't need the theory to be productive.
That's all just to say that the issue isn't FP in general, but the way FP has been implemented in beginner-unfriendly ways.
Seems pretty similar to functional programming in that respect. When I write code in languages like Haskell, I tend to focus the most on two things:
1. The conceptual organization of the code (≈ layout)
2. The interfaces between components (≈ routing)
Static types and functional programming naturally lean into this: types provide a first-class way to sketch out layout and interfaces in code without needing to implement the code in full detail. I'm drawn to static types less because of correctness or preventing bugs—although I can't complain about that!—and more because they give
me a quick, high-level sub-language to sketch out and iterate on the design of my code. Those same types then act as guideposts for how the codebase fits together, making it easier for me to understand projects written by others or revisit code I wrote but don't remember well myself.
You always get functions handed to you in programming languages. CPU instructions are handed to you. Scheme, has a small core of special forms which are handed to you. You build up bigger specific things from small general things.
In factorio you create bigger functions from smaller ones as explained in the article in great detail. The routing and layout part is about organization, but the more abstract notions of combinations and ratios are "functional" in the sense of the article.
Perhaps we can spice up Haskell programming with random alien attacks?
I think games like these have the advantage that they immediately become a tool to be toyed with, although many still complain that getting into Factorio isn't too easy. Until math or a programming language becomes a tool, you have to invest a bit more into it.
The "building blocks" (actually, the only data structure) of logic programming languages like Prolog, ASP, Mercury, Oz, etc are ... relations. Which map elements of sets without specific inputs and outputs. Put that in Haskell's pipe and smoke it.
OK, but now let's ask the important questions: has anyone implemented SLD(NF)-Resolution in Factorio, yet?
I wonder what the OOP version of that would look like. Trivially, you can imagine that an assembling machine is an object to which you can send a message CopperPlate, and that will reply with CopperWire, CopperWire. I've been thinking about factories like you see in "How it's made" and how you can imagine the machines in terms of functions with an input and an output, object to which you pass something and receive something back, or even "ingredient flow" where the focus is on the product and the different steps and not the transformations.
The line between functional and object oriented actually gets very blurry when you take OO in its traditional sense, i.e. if you accept message passing between objects as the defining feature.
if the object becomes a pure blackbox and all you care about is what it sends and receives then this is hard to distinguish from the functional thinking, because even functions at their core usually have an imperative implementation, they just hide it away.
Erlang has been brought up in the thread and it's a good example of this because people use it as an example of both functional programming and maybe the closest thing to Alan Kay's original ideas about OO.
Only different is OO languages typically give you an implicit {hierarchical state, logging, OS interfacing}, monad for free (or at least under the generalized async monad), FP makes you request all that yourself.
if you take mutation of state out of the object, and we leave aside all the category theory part of fp then is more a matter of where functions are defined/how they organised
If that were Haskell instead of python, it would still work, because tmp is never mutated. So it's not really state in that sense, it's just a binding.
x input = show tmp
where tmp = input * 5
It would be a different story if you had something like
class IntState:
def __init__(self, val):
self.val = val
def x(input):
self.val += input
return str(val)
When I play factorio I am thinking about the conveyer belts as CSP channels and the grabber arms and factories as processes. Nothing to say the processes aren’t functions of course.
Tangentially related: I would love a brilliant game dev to replace my hierarchical folder view with a recursive / graphical overview that lets me see the summarized structure/relations of an application (or set of services?).
Seems like leveraging our spatial system to communicate locality and purpose while hiding the innards would be very beneficial. I don't think you'd need to go full-on graphical programming language to achieve it either.
Lot of games develop some kind of logical thinking. RTS games in particular.
I remember playing Age of Empires 2 as a teenager and enjoying the amount of choices I have to win the game. Plus, the game teaches you about efficiency like few other games at the time. Each game, the sheer amount of resources and technologies you had to track in real time is equivalent of small bussines.
Then came Starcraft and logical thinking was replaced with player APM.
I think it's clear to most people who build things that functional programming only appears in the wild when a programmer sets out to build something with functional programming. Those of us who are not taken by this hobby would never use it for anything.
Functional programming is everywhere. Many aspects of for example modern Java also move in the direction of functional programming.
Those who never learn it are just stuck writing software in a more complicated and less readable way.
Learning FP and using it where it makes sense can do wonders to the quality of code you write. And over the past years many (even "traditional") languages have recognised and embraced that fact.
We use pure functional programming in production to manage airline pairing/rostering and optimisations. Each customer has about 150k lines of pure functional code running on their servers. Also, Google “Elm” for examples of a pure functional language being used in production by other companies and how Facebook and other companies use Haskell in production.
> You might have heard people say that functional programming is more academic, and real engineering is done in imperative style.
Real Engineering is done in imperative style. There are very very few projects done in pure functional style. Sure it can be possible, there are always a few FP projects sprinkled around eg Spark has done great. But FP really is a niche specialty. It makes me think it just isn't the right tool for the job.
From my experience, real engineering is done in a multi-paradigm style. Some functional, some oo, some imperative, etc. As a general rule, functional style is easier to reason about (and test) for smaller pieces of code (ie, pure functions, function composition, etc) but can be harder to reason about for the larger code base. As such, it's very common to see as many functions as possible be done in a functional style.. but the overall system include lots of non-fuctional things.
Indeed, I'd say that a lot of the software development I do isn't Real Engineering. And that's fine! I have a lot of respect for the people who make 50-story skyscrapers. But a lot of the time what people need is a modest one-story apartment, a redone kitchen, a backyard doghouse. Or a movie set that just looks like an apartment.
Lots of "real" engineering is based on algebraic manipulation, which has more in common with declarative/functional programming than with imperative/procedural programming.
Not to mention that anything that goes through a spreadsheet relies on functional programming.
> I’m going to show you that real engineering is functional, and I’m going to illustrate it using a computer game that is designed by engineers for engineers.
Pretty much all the domain code I write at work is in a functional style. Because D makes this easy and convenient, it's just what we end up using. Turns out dataflow is easier to follow than control flow.