[HN Gopher] The Big Oops in type systems: This problem extends t...
       ___________________________________________________________________
        
       The Big Oops in type systems: This problem extends to FP as well
        
       Author : ksymph
       Score  : 49 points
       Date   : 2025-07-31 19:49 UTC (2 days ago)
        
 (HTM) web link (danieltan.weblog.lol)
 (TXT) w3m dump (danieltan.weblog.lol)
        
       | dang wrote:
       | Recent and related. Others?
       | 
       |  _The Big OOPs: Anatomy of a Thirty-Five Year Mistake_ -
       | https://news.ycombinator.com/item?id=44612313 - July 2025 (181
       | comments)
       | 
       |  _The Big Oops: Anatomy of a Thirty-Five-Year Mistake [video]_ -
       | https://news.ycombinator.com/item?id=44596554 - July 2025 (91
       | comments)
        
       | hackyhacky wrote:
       | Maybe I'm just missing something, but the "domain expert" that is
       | described here is just... a function? The big win in Clojure is
       | apparently using code instead of types?                 (defn
       | apply-shipping-rules [order]         (cond-> order           (and
       | (= :premium (:customer-type order))                (> (:order-
       | total order) 100))           (assoc :shipping-cost 0)))
        
         | sirwhinesalot wrote:
         | Yes, the point of the article is that people should do this (as
         | is common in Clojure) rather than try and encode the rules in
         | the type system (be it as a class hierarchy or a sum type).
        
           | GiorgioG wrote:
           | So (I don't know Clojure) - is the author saying everything
           | should be a map/dictionary? That sounds like complete chaos -
           | I'm not an OOP proponent.
        
         | rjknight wrote:
         | The "domain expert" is the business-person who is, it is
         | suggested, more capable of reading and comprehending the
         | Clojure code than the Haskell code.
         | 
         | Since there is an equivalence between types and propositions,
         | the Clojure program also models a "type", in the sense that the
         | (valid) inputs to the program are obviously constrained by what
         | the program can (successfully) process. One ought, in
         | principle, to be able to transform between the two, and
         | generate (parts of) one from the other.
         | 
         | We do a limited form of this when we do type inference. There
         | are also (more limited) cases where we can generate code from
         | type signatures.
         | 
         | I think op's point is that the Clojure code, which lays the
         | system out as a process with a series of decision points, is
         | closer to the mental model of the domain expert than the
         | Haskell code which models it as a set of types. This seems
         | plausible to me, although it's obviously subjective (not all
         | domain experts are alike!).
         | 
         | The secondary point is that the Clojure system may be more
         | malleable - if you want to add a new state, you just directly
         | add some code to handle that state at the appropriate points in
         | the process. The friction here is indeed lower. But this does
         | give up some safety in cases where you have failed to grasp how
         | the system works; a type system is more likely to complain if
         | your change introduces an inconsistency. The cost of that
         | safety is that you have two representations of how the system
         | works: the types and the logic, and you can't experiment with
         | different logic in a REPL-like environment until you have fully
         | satisfied the type-checker. Obviously a smarter system might
         | allow the type-checker to be overridden in such cases (on a
         | per-REPL-session basis, rather than by further editing the
         | code) but I'm not aware of any systems that actually do this.
        
           | vips7L wrote:
           | I honestly doubt a business person would be able to read
           | Clojure. I've been programming for 15 years and it doesn't
           | make any sense to me.
        
             | senderista wrote:
             | I've been reading and writing English for half a century
             | and Chinese doesn't make any sense to me, so I doubt any
             | ordinary human could read it.
        
               | vips7L wrote:
               | That's quite the false equivalence.
        
               | michaelsbradley wrote:
               | How so?
        
           | hackyhacky wrote:
           | > The secondary point is that the Clojure system may be more
           | malleable - if you want to add a new state, you just directly
           | add some code to handle that state at the appropriate points
           | in the process.
           | 
           | That's all certainly possible. But the same could be said of
           | Python or JS. So if the big point here is "we can model
           | business decisions as code!", I fail to see the innovation
           | because we've been doing that for 50 years. Nothing unique to
           | Clojure.
           | 
           | You could even do it Haskell if you want: just store data as
           | a Map of properties and values, emulating a JS object.
        
       | sirwhinesalot wrote:
       | I agree with the article, but I will note that we have a great
       | tool for this problem that is (or at least can be) "statically
       | typed": the relational model. Databases are precisely what you
       | want for this sort of problem (even better if it's Datalog and
       | you can encode rules that derive relevant information).
       | 
       | Most mainstream languages are very poorly equipped to do
       | relational modeling. ORMs are a disaster (object-relational
       | mismatch) and you don't necessarily need an actual database
       | running in the background.
       | 
       | Clojure's approach is superior to the class hierarchy or sum type
       | solution for this sort of very loose business domain modelling,
       | for the reasons stated in the article, but it's also a local
       | optima, and so is the "fat struct" solution (which is the
       | statically typed equivalent). Even entity component systems are
       | but a shadow of the relational model.
        
         | jiehong wrote:
         | It's part of the answer (the business logic stays as functions
         | as expressed in the article).
         | 
         | I'm glad people seem to have left behind the feeling that
         | relational model is bad during the NoSQL era.
        
         | mcphage wrote:
         | > I will note that we have a great tool for this problem that
         | is (or at least can be) "statically typed": the relational
         | model. Databases are precisely what you want for this sort of
         | problem
         | 
         | Relational databases still lock you into a specific design, and
         | trying to work contrary to how your application was designed
         | 10-15 years ago leads to terrible performance, high costs, and
         | bugs galore.
         | 
         | It may be better than other options, but it's still not exactly
         | a solved problem.
        
       | rorylaitila wrote:
       | I mostly agree. I have quipped once that I write "spaghetti and
       | meatballs" code. The meatballs are the core domain objects,
       | explicitly typed. The spaghetti is the business rules, untyped.
       | With experience you get a good intuition where to draw the line.
       | But the untyped code needs extensive testing.
       | 
       | Where I disagree with the article is on refactoring. It's
       | identically hard both ways. Migrating to new business rules while
       | simultaneously running the old and new system is the hard part. I
       | don't find static typing helps or hurts me in particular.
       | Compiler warnings are useful, but my unit tests catch the dynamic
       | parts as well. Either way a lot breaks and often needs temporary
       | scaffolding between the versions.
        
       | moomin wrote:
       | I feel like this article is missing the point by a country mile.
       | FP proponents very much know that requirements can change and
       | wreak havoc with their type systems forcing them to change large
       | numbers of likes. What the author is missing is that this is be
       | welcomed and vastly preferable to the situation we find ourselves
       | in with Python codebases where those lines still need updating
       | but the code will happily run incorrectly if you fail to find
       | them all. Switching off the alarm doesn't stop the fire
       | spreading.
        
         | qayxc wrote:
         | I don't agree with that assessment. The problem is that,
         | staying with your analogy, the fire alarm goes off every time
         | someone has to use the toilet. Plus it's not just the alarm
         | going off, it's the entire fire department showing up and doing
         | a forced rearranging of the furniture throughout the entire
         | building each time.
         | 
         | And no, requirement changes don't have to cause that to happen
         | and they don't have to wreak havoc throughout your application
         | due to poor design decisions.
         | 
         | It's fine to encode rules directly into the type system, but
         | only for rules that are known to be fixed (or at least not
         | likely to ever change) throughout the lifetime of the project.
         | For many business rules, however, this unfortunately doesn't
         | apply.
        
       | fellowniusmonk wrote:
       | A mereological nihilist will never have anything but primitive
       | types.
       | 
       | Everything more complex than those building block aren't in
       | reality a Type.
       | 
       | Reality doesn't consiste of: X type made up of these primitives
       | and other defined sub-types and let's hide the primitives as far
       | down as we can.
       | 
       | It's instead primitives arranged X wise.
       | 
       | Or mapped a little better to programming terminology: A Schema.
       | 
       | It's about having the mental model that complex types can be
       | useful as an abstraction but they aren't real and aren't worth
       | fighting for or defending.
       | 
       | Types are for devs, devs aren't for types.
        
       | jayd16 wrote:
       | It's supposed to break when your assumptions break. That's the
       | whole point.
        
       | jiggawatts wrote:
       | I've watched a few good talks by people that have coded this kind
       | of thing at the maximum level of scale and complexity, such as
       | Amazon's checkout system.
       | 
       | The endgame of this problem always turns into some sort of "log
       | of events" with loosely coupled subscribers.
       | 
       | A single state machine suffers from a combinatorial explosion of
       | states as it has to handle every corner case, combinations of
       | every scenario, etc...
       | 
       | What if a single shopping basket contains _both_ a digital good
       | and a physically shipped one? What if _some_ items are shipped
       | separately and /or delayed? Etc...
       | 
       | Instead the business rules are encoded into smaller state
       | machines that listen to events on the log and pay attention only
       | to relevant events. This avoids much of the complexity and allows
       | the OOP types to remain relatively clean and stable over time.
       | 
       | Now the "digital goods" shipping handler can simply listen to
       | events where "delivery=authorized" and "type=digital", allowing
       | it to ignore _how_ the payment was authorised (or just store
       | credit!) and ignore anything with physical shipping constraints.
       | 
       | It then writes an event that marks that line item in the shopping
       | cart as "delivered", allowing partial cancellations later, etc...
        
       | yehoshuapw wrote:
       | while this does bring up a valid point,
       | 
       | "classic" sql databases are still safer for many things then
       | mongodb.
       | 
       | it is _easier_ to do away with types and constraints, but in many
       | cases they do end up being important safeguards
        
         | dboreham wrote:
         | The same abstract pattern exists with many (most?) annoying
         | things in the computing field: people focus on solving problem
         | #1 but it turns out there's a complementary problem #2 that is
         | now worse, that they either didn't know about or didn't much
         | care about.
        
       ___________________________________________________________________
       (page generated 2025-08-02 23:00 UTC)