26 ms·
This is hard to reconcile with type theory for me. NULL, to me, implies and uninhabited type, i.e. there can never be a value with a NULL type. Using null for
by davemp 8y ago
This is hard to reconcile with type theory for me.
NULL, to me, implies and uninhabited type, i.e. there can never be a value with a NULL type. Using null for a "data isn't there, apply, available, etc" seems like an abuse of the type system. I see no reason that the former needs to be supported at the type level. These properties are just responses to queries, not some mystical, uninhabitable oblivion. Unnecessary type features just make verification and learning a language much more difficult.
- SpicyLemonZest 8y agoIt needs to be supported at the type level, whether by null or by options, simply because “data not available” is a common value people need to use. When there’s no good way to express it, they’re forced to invent special sentinel values, and you end up in the situation where array index -1 means “value not found in the array”.
- davemp 8y agoYes, option types are awesome. No, they are not nulls. Algebraic data types are not direct support "no data found at the type level". Algebraic types are really just a fancier enum/union type. It just so happens that inventing special sentinel values is awesome when you have an algebraic type system to check your work.
- SpicyLemonZest 8y agoThey’re not direct support, but option types only work in languages with the right syntax and tooling to make them work. C union types, for example, aren’t really capable of providing a null replacement simply because they’re so complex to use.
- HumanDrivenDev 8y agoThey’re not direct support, but option types only work in languages with the right syntax and tooling to make them work. I strongly disagree. You don't need pattern matching syntax to use option types effectively. All you need are the right methods - map, flatMap, getOrElse etc etc. Any language with inheritance and dynamic dispatch can implement a good option type. Even in languages with pattern matching, I never reach for it when dealing with options.
- dtech 8y agoTake a look at Kotlin or Typescript†. Basically, they decided to fully design the language with support for null-as-option. That means several things: * T (non-nullable) and T? (nullable) are different types. T? = T | null * Where T is expected T? is not accepted, but where T? is specified T is also accepted * T? is automatically cast to T in the places where it's asserted to be not null, e.g. within an if(x != null) branch * Method calls are not allowed on T? (unless the function specifies it can handle null) * There's syntax for providing a value in case of null. (x ?: fallback) in Kotlin, (x || fallback) in Typescript. It's a much more pleasant developer experience than the Option ADTs/Enum types from Scala or Haskell, which the same amount of safety. Typescript goes even further and has the best enumeration support I've seen any language have. T | U is a fully valid type, and if T | U is asserted to be one of them it is automatically cast to T/U. It is a very natural and efficient way of building ADTs [1] † Typescript 2.0+ with --strictNullCheck on [1] https://www.typescriptlang.org/docs/handbook/advanced-types.html https://www.typescriptlang.org/docs/handbook/advanced-types.... , Discriminated Unions header
- davemp 8y agoThese are great features, but they are really just syntactic sugar over algebraic types. It's not a more pleasant developer experience than sum (Option) types, it's a more pleasant experience with sum types. Ex: macro! unwrap(x, fallback) { match x { Some(n) => n, None => fallback }; } > Typescript goes even further and has the best enumeration support I've seen any language have. T | U is a fully valid type, and if T | U is asserted to be one of them it is automatically cast to T/U. It is a very natural and efficient way of building ADTs That's pretty cool. It seems like refinement types. [1] [1]: https://en.wikipedia.org/wiki/Refinement_(computing)#Refinement_types https://en.wikipedia.org/wiki/Refinement_(computing)#Refinem...
- nostrademons 8y agoIt's subtly different because of the implicit coercions and smart casts. You can always pass T to a function that takes T?, while in Haskell/Rust you would need to pass Some(t). Similarly, Kotlin does control-flow analysis and converts all T?s inside an "if (t != null) ..." block or after an "if (t == null) return" statement into a T, which dramatically reduces the amount of try!/unwrap() calls that I used to see littering early Rust code. There's better syntactic sugar for it in Rust now, but the point is that Kotlin doesn't need nearly as much syntactic sugar because nullable is integrated with the typechecker and flow analysis.
- dragonwriter 8y ago> Yes, option types are awesome. No, they are not nulls. No, but they serve a superset of the semantic functions of nulls, better than nulls do.
- bootlooped 8y agoI have worked with a MySQL database where the designer(s) decided that, on many of the tables, -1 should represent no value instead of null. As you can imagine, this has caused some problems when they've done this with columns representing dollar amounts. This was done because of their belief that having any nulls in the table is the kiss of death for performance; they've used the phrase "tablescan" a lot. I have not been able to find a basis for these claims.
- fphhotchips 8y agoDatabases, and MySQL in particular because of how many of it's defaults are pants-on-head nonsensical, are a haven of cargo cult performance rituals. I have a suspicion this is because, rather than analysing their own N! loops/queries, it's easier for mediocre programmers just to blame the database.
- giornogiovanna 8y agoNULL isn't the uninhabited type, that's the bottom type. NULL is a value that inhabits every type.
- davemp 8y agoThank you. I got confused on nomenclature because of a null pointer's similarity to the bottom type. I was trying to say that having a NULL value that inhabits every type seems silly as not every set of values has the NULL value. Considering that NULL can be represented as a special case of sum types, it seems even sillier to mandate such a value on all types. Using both NULL and nullable seems very confusing as well.
- yxhuvud 8y ago> NULL is a value that inhabits every type. Not in all type systems. Particularly, type systems which has union types may chose to simply create a separate type for NULL. There are also variants that have separate NULL types for different base types, which also invalidate your claim.
- ArchTypical 8y ago> Not in all type systems I think this is inaccurate. We are talking about computer science, which is important and a constraint around the general type theory. A type system is different than how you interact with it, so dispensing with language-specific symbolic representation further normalizes the discussion. Fundamentally, a (computer science) type is a representation of binary, for the most part, data. That representation has to inhabit some part of bounded memory. When that memory is initialized (empty), it's some form of NULL, for a lack of another term. It exists for every type system in computer science. > There are also variants that have separate NULL types for different base types, which also invalidate your claim That's not the same thing. Different NULL types make sense for different sized discrete (fixed bounds) memory allocation. A unicode character has a fixed size allocation, while a string might be unbounded allocation (it grows in some fashion, as needed). Edit: Kneejerk downvoting, classy.
- 8y ago
- kazinator 8y agoThis is clear in (Common) Lisp. There is a null class/type whose one and only instance is the special object nil. This nil also itself names a type which contains no instance: its domain of values is the empty set. This is the type at the bottom of the type spindle, corresponding to the NULL that you're talking about. nil is a special self-evaluating symbol representing Boolean false, the empty list, and this bottom type. So you see, if we just don't conflate the null object with the null set type, everything works out.