Same goes for a value of type Employee; if I might or might not have an Employee (for instance, if the lookup function doesn't find someone with that employee number) then I have to use Maybe Employee.
Scala has the same concept with (IIRC) the Option type. But Scala also inherits null references from Java. In Java a reference to an Employee might be an optional value (so null is allowed) or it might be a required value (so null is not allowed). Scala has to play well with Java so anything has to be allowed to be a null reference. Except that Integers in Java (and hence Scala) aren't references, so I can't have a null reference to an Integer.
So now my "Option Employee" might wind up being a null reference to the Option, or it might be an Option that is empty, or it might be an Option that contains a null reference to the Employee, or it might actually have an Employee in it.
Gahh.
The same is true of C++. Values and references in C++ can't be null. Pointers can be null, but that's a lower-level feature that doesn't have an equivalent in idiomatic Haskell.
In idiomatic Haskell, if you need something like a pointer you have several choices. If you're writing parallel code your best bet is STM. If you're writing code in IO, you can use an IORef. If you don't want that restriction, you can use an STRef.
(I'm aware that you probably know all this, but other people reading the thread might not.)
x,y::Integer
x = x + 1
y = undefined a,b::Integer
a = div 1 0
b = sum [1..]If you have a mutable object anywhere in your codebase, the compiler can not reuse calculated values, ignore unneeded code, or map a set of independent output sequences[1] at your source code into highly interleaved single threaded asynchronous output, like Haskell's green threads do.
[1] I'm yet to see an imperative language (and "mostly functional" is imperative) that has the concept of "output sequence", instead of "execution sequence", but I don't know enough to claim it's impossible.
C++ "failed"?
> the OO and functional features don't interact well
How don't they? Before C++ had lambdas, programmers would define a class with overloaded operator() and use that instead, every time. Now the language provides a way to easily generate the class with its members and constructor and operator() automatically - which is basically what functional languages turn lambdas into. You could make the same argument that "procedural and OO features don't interact well", but C programmers were (and still are) using structures and function pointers to accomplish much the same effects.