25 ms·
the type `null | true | false` is different from `true | false`, a type checker can assert that you handle the `null` case before using a function that wants a
by evomassiny 4y ago
the type `null | true | false` is different from `true | false`, a type checker
can assert that you handle the `null` case before using a function that wants a boolean.
This is how rust handles it (with the Option<T> type).
- harperlee 4y agoIn particular, you may want this to signify “I dont know” with NULL, just as in SQL. See the Wikipedia page for ternary logic for more info.
- alexvoda 4y agoNote that 3VL (3 valued logic) is one of the more criticized aspects of SQL. 3VL is a gigantic leap of of complexity over 2VL (boolean). The number of possible operations is a lot higher and the choice of operations is not standardized. To quote wikipedia: "In two-valued logic there are 2 nullary operators (constants), 4 unary operators, 16 binary operators, 256 ternary operators" And we all agree which of those 16 is named what. "In three-valued logic there are 3 nullary operators (constants), 27 unary operators, 19683 binary operators, 7625597484987 ternary operators" There is no standard meaning of the 3'rd value and of the operations involving it. That is not to say that 3VL isn't useful. I believe the reason for the criticism of 3VL in SQL it that the system made those choices for you and those choices are not always intuitive. Therefore a null in one attribute in one relation might mean something very different from a null in another attribute in another relation. Also note that as opposed to digital signal processing (where binary and ternary refer to the number of possible values a bit/trit can have), when discussing logic arity (nullary, unary, binary, ternary, n-ary) refers to the number of arguments required by a function as opposed to the number of values the arguments can have (univalent, bivalent, trivalent, k-valent). This is confusing because the terms are used interchangeably.
- freilanzer 4y agoYes, so it's just about returning a (Maybe = Just bool | Nothing). No null needed.
- evomassiny 4y agoexaclty, whether you call it 'Nothing' or 'null' does not matter, as long as it represents a distinct type than 'true' or 'false'
- freilanzer 4y agoNull for me is a null pointer, and thus there's a difference. Anyway, if that's all you want than Haskell, etc. definitely handle that case.
- nerdponx 4y agoThe word "null" means "missing value" in e.g. SQL and most data science / analytics contexts. It's unfortunately an overloaded term with two different meaning. Conflating the two things is where we get the egregious mistake of using null pointers to represent null data!
- avgcorrection 4y agoThat doesn’t make sense. `null | false | true` is not equivalent to `Option<bool>` or `Option<false | true>`. Just like `zero | one | two` is not equivalent to `Option<one | two>`. Assuming that `true | false` is equivalent to something like `enum { true, false }`.
- evomassiny 4y ago> Just like `zero | one | two` is not equivalent to `Option<one | two>` Isn't it ? both cases represent a type than can express 3 variants
- valenterry 4y agoIt is equivalent in the amount of information you can encode, but not in how you can use it. Classical example is wrapping multiple times: Option<Option<one | two>>. If you have null | null | one | two, well... that just boils down to null | one | two.
- Nullabillity 4y agoThose two types are indeed equivalent by themselves. The problem comes when you want to store them somewhere nullable. `zero | one | two | zero` flattens back down to `zero | one | two`, you can't distinguish between the two zero/null cases. On the other hand, `Option<Option<one | two>>` allows you to distinguish between None and Some(None). This makes union types unsound in the presence of type parameters/generics. TypeScript supports both anyway, because Hejlsberg cares more about being able to type existing JS antipatterns than about providing a sound type system.
- valenterry 4y ago> This makes union types unsound in the presence of type parameters/generics. I'm not sure if "unsound" is a good adjective here. There are cases where this is actually desired behaviour and the rules can definitely be "sound". For example, I might want to know what errors can appear, but not care where they come from. So `ErrorA | ErrorB` is what I want to see, not some nested structured that allows me to differentiate where ErrorA came from in case that there are multiple possible options.