Deterministic Core, Non-Deterministic Shell

Posted by brandon_bot 12 hours ago

Counter49Comment11OpenOriginal

Comments

Comment by rgoulter 1 hour ago

I think the main insight from "functional core, imperative shell" is more about structuring the code so as to be easy to test.

Without that structure, code tends to be difficult to test, since the impure stuff like network requests is part of the same sequence of statements as the logic you want to test. (That is: pure code is easier to test (but harder to write real programs with).. so, "arrange the code so you've got a well tested core" is a good strategy).

The nice part about the pure/functional is that you know for the same inputs, you always get the same outputs. -- I think if you want to say, "well, this stateful object is still pure (if you consider the state part of the input" then sure, I guess.

Comment by kccqzy 10 hours ago

I agree with the thrust of the article but I want to quibble with one thing: the article says “calling RNGs that aren't seeded” doesn’t count as deterministic behavior, but randomized algorithms often have simpler implementations and better asymptotics than non-randomized algorithms while having statistical guarantees (“almost surely”) on their properties. Two of my favorite examples: (1) a randomized quicksort where choosing the pivot randomly in each iteration is simpler and better than deterministic methods of choosing the pivot; (2) a randomized treap gives you a balanced binary search tree with far simpler implementation than say a red black tree. And that’s besides the more utilitarian security benefit of using randomness inside hash functions to protect against HashDoS attacks.

So I’d implore the author to delete this restriction. Even when randomized algorithms produce different outputs (the treap giving you differently shaped trees with the same sequence of inserts) these outputs have properties that can be checked statistically.

Comment by Retr0id 5 hours ago

Anything you can do with ""real"" randomness can be done just as well with a seeded [CSP]RNG, including DoS prevention if you can keep the seed secret.

If you really want true RNG, you can inject a deterministic RNG at test-time and use a real one otherwise.

Comment by _0ffh 5 hours ago

Easily circumvented: Generate a random seed in the shell and pass it to the core.

Comment by kccqzy 14 minutes ago

Great, that’s the ideal case. But in many languages and many libraries it is all but impossible to pass on a seed to everything that uses randomness, unless you control all these libraries.

That’s why as a matter of practicality I’d advocate otherwise.

Comment by consuming2 6 hours ago

This split is familiar from Temporal.io: workflows are deterministic while activities are idempotent.

Comment by Kinrany 5 hours ago

I wonder if languages could and should allow enforcing both properties.

Comment by giovannibonetti 5 hours ago

For frontend web development, Elm enforces a pure core (pure > deterministic).

Comment by orielhaim 5 hours ago

[dead]

Comment by Retr0id 5 hours ago

I've been pondering something I call "slop core, artisanal shell", as a way of keeping vibecoding under control. Slop core might sound like the thing you want to avoid, but as long as it's purely-functional (or perhaps, merely deterministic) it should be robustly testable. The "artisanal shell" keeps the thing human-understandable and human-modifiable, as long as you put some thought into the API boundaries.

Comment by giovannibonetti 5 hours ago

I have been trying to tell the folks at work the same thing. Ideally, using a language that goes in that direction. For frontend web development, for example, there is Elm, which is pure and functional.

Comment by Founderarcstone 12 hours ago

great work the world needs more of this!

Comment by timur860 11 hours ago

[flagged]

Comment by Wren_ops 7 hours ago

[dead]