<story><title>Types as axioms, or: playing god with static types</title><url>https://lexi-lambda.github.io/blog/2020/08/13/types-as-axioms-or-playing-god-with-static-types/</url></story><parent_chain></parent_chain><comment><author>hardwaregeek</author><text>One corollary about using positive space is that you realize we overuse booleans a lot. I routinely use a lot of boolean logic in my JavaScript and TypeScript code. I use it to decide when to display a component, when a component is being hovered, when it&amp;#x27;s odd, etc.&lt;p&gt;Recently I wrote a simple tree walk interpreter and had to implement boolean unary negation:&lt;p&gt;&lt;pre&gt;&lt;code&gt;     (UnaryOp::Not, Value::Bool(r)) =&amp;gt; Ok(Value::Bool(!r)),
&lt;/code&gt;&lt;/pre&gt;
Why is this line important? Well it&amp;#x27;s quite possibly the first[^1] time I have used the boolean negation (!) operation in Rust!&lt;p&gt;Turns out, when you have proper enums, booleans aren&amp;#x27;t the best tool. Something like `isLoading` can now be `data LoadingState = Loading | Success`.&lt;p&gt;Why is that better? Well if you want to add a third or fourth state, it&amp;#x27;s trivial.&lt;p&gt;&lt;pre&gt;&lt;code&gt;     data LoadingState = Loading | Success | Failure
&lt;/code&gt;&lt;/pre&gt;
You can even give it data to pass along&lt;p&gt;&lt;pre&gt;&lt;code&gt;     data LoadingState a err = Loading | Success a | Failure err
&lt;/code&gt;&lt;/pre&gt;
Turns out you can have a lot more states than two. Often times in the equivalent boolean case you end up with a couple booleans: isLoading, isError, etc.&lt;p&gt;But then you end up with invalid boolean states! Like isLoading = true, isError = true. Huh? By making a multi-state type, you can restrict to only the possible states.&lt;p&gt;[^1]: Meh actually more like 5th but you get my point</text></comment>
<story><title>Types as axioms, or: playing god with static types</title><url>https://lexi-lambda.github.io/blog/2020/08/13/types-as-axioms-or-playing-god-with-static-types/</url></story><parent_chain></parent_chain><comment><author>piinbinary</author><text>This reminds me a lot of Parse, don&amp;#x27;t Validate (by the same author, apparently): &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;lexi-lambda.github.io&amp;#x2F;blog&amp;#x2F;2019&amp;#x2F;11&amp;#x2F;05&amp;#x2F;parse-don-t-validate&amp;#x2F;&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;lexi-lambda.github.io&amp;#x2F;blog&amp;#x2F;2019&amp;#x2F;11&amp;#x2F;05&amp;#x2F;parse-don-t-va...&lt;/a&gt;&lt;p&gt;I think there&amp;#x27;s another reason to make invalid states inexpressible in the type. When you need to change existing code (perhaps years after it was first written) in a way that breaks key assumptions, you find that the current types don&amp;#x27;t allow expressing that change. This is a good warning sign that other code will need to be updated to take the new states into account. Without the type enforcing that invariant, it might have been much harder to tell that this particular change (out of all the changes you make over the years) is the one that breaks a key assumption. (A key assumption that might have been forgotten by now!)&lt;p&gt;Types become a message to your future self.</text></comment>