Conversation

I think of all the programming advice I've ever practiced, I think that "make invalid states unrepresentable" is the single greatest source of design damage that I've had to undo.
9
67
I just replaced 4 types with 1 type that can possibly be in some invalid states, wrote a validation function (that is only used in tests really) and then generalized all the code to handle nil/empty/invalid substates transparently. This keeps happening.
2
17
There are some invariants that can't be encoded into the type system, but also shouldn't be encoded into discriminated cases either. Frequently, manipulating product types with degenerate cases are dramatically simpler (read: less dispatch/branching/matching) than sum/union types
3
17
Yeah it was maybe meant as a nice design mindset but doesn't work as a hard & fast rule.
1
What I really want is the ability to specify _named_ validation rules and then apply them over constrained scopes or at specific points in the code.
1
1
Though I need pretty rich constraint power. To invent some syntax for an example: struct Infix [ field operators ListOf[Operator] field operands ListOf[Operand] constraint (operators.length = operands.length - 1) ]
2
But critically, I don't want that constraint enforced while I'm _building_ such a structure. And I also don't want to have to re-declare two variants of the structure.
1
3
I need something like: struct InfixShape { operators: List operands: List } type ProperInfix = InfixShape & { operators.length = operands.length - 1 }
2
1