The power of option types is in what they do to the rest of the language
I was recently reading Real problems with functional languages (via), where I ran across the standard explanation of why option types matter. As I read it (and not necessarily as it's really written in that article), they matter because they force you to deal explicitly with null values.
Reading this sparked a little light in my head, because this isn't really correct. Modern compilers do not need an explicit type to force you to do this checking; with data flow analysis inside functions, they are perfectly capable of forcing you to check whether or not a variable is null before you make any other use for it (and only allowing that use in a code path where you had proven the variable wasn't null). So why don't they?
The simple answer is that a compiler that required this would be insufferable to use, because every single function where you had a potentially nullable entity would need its own set of checks (unless the compiler had extremely reliable inter-function analysis), all the way up and down the call stack. It wouldn't matter that every path to this function having this entity was already checking for nulls; you'd have to do it again, over and over. In practice, what people using the compiler (and the language) would insist on is some sort of notation for 'this cannot ever be null', which would allow you to not check in any code that only dealt with such variables.
(The compiler would then require that you could only return, assign to, or otherwise set those entities to non-null values, by requiring checks beforehand. But they would be localized checks.)
This leads me to my new view of the real power of option types, which is that the power of option types is that they let you check for null only once, instead of everywhere in your program. Having option types makes it ergonomic to create types that are defined so that they cannot be null and then have the compiler enforce this, while still giving you an escape hatch for situations where you have to return something other than a legitimate value of the type.
Of course, this is not the only thing option types can do. Even in a language where you can't restrict your types this way, option types provide you a way to make people explicitly consider errors, null returns, or whatever by wrapping up the value they really want inside something that forces them to confront the issue and blows up if they don't. But it doesn't do it as pervasively as 'cannot be null' types, and to the extent that you try to make it pervasive, it becomes more and more annoying, because it is exactly those 'prove it's not null over and over again' checks being enforced by user-created types.