| > With nicer syntax, nulls are equivalent to Maybe types. No they're not, since you can't nest NULLs. Say I have a database of "Users", with "birthdates" mapping a "User" to a "DateOfBirth" and "spouses" mapping a "User" to a "User", I can look up a User's DateOfBirth either using a Maybe or by allowing NULLs: -- Maybe
getDOB :: User -> Maybe DateOfBirth
-- Nullable
getDOB :: User -> DateOfBirth
I can also look up a User's spouse with either a Maybe or a NULL: -- Maybe
getSpouse :: User -> Maybe User
-- Nullable
getSpouse :: User -> User
So far they're pretty much equivalent. However, what if I want to look up a spouse's DateOfBirth? -- Maybe
spouseDOB :: User -> Maybe (Maybe DateOfBirth)
spouseDOB u = fmap getDOB (getSpouse u)
-- Nullable
spouseDOB :: User -> DateOfBirth
spouseDOB u = let s = getSpouse u
in if s == NULL then NULL
else getDOB s
These are no longer equivalent. In the Maybe case we can distinguish between three kinds of values:- `Nothing` indicates that we can't find the spouse - `Just Nothing` indicates that we can find the spouse but not the DOB - `Just (Just x)` indicates that we found both the spouse and the DOB In the nullable case we can only distinguish between two kinds of values: - `NULL` indicates that either we couldn't find the spouse or we couldn't find the DOB, but we don't know which - Anything else indicates that we found the spouse and the DOB The Maybe approach gives us strictly more information; although we can choose to ignore it if we like, either by using `join` or by replacing `fmap` with `>>=` (AKA "bind", which is a combination of `fmap` and `join`). |
Your nullable example is better compared to this, which also discards the required information:
Likewise, the nullable case, modified to preserve it (in a language which actually has nulls this time): Maybes are just pointers. There's nothing magic about them.