The “error state” is not a well defined term as far as I know. Who’s to say that “not found” is not an “error state”?
Anyways, the point is that Julia is a dynamic language and normally uses Union return types, not sum types. If you need to return an error value with more information than nothing, you can return any other type you like. If a function has more than one “error state”, you can return a larger union, like Union{TheNonErrorReturnType, MyErrorType1, MyErrorType2}.
I agree that Some{T} is needed for some functions, but note that Union{Some{T}, Nothing} is still a union type, not a sum type. The Some{T} type is only needed for functions where nothing is one of the possible “non-error values”. But there are plenty of functions where that is not an issue. To take an artificial, toy example:
using Distributions
struct TooSmall end
struct TooBig end
function my_quantile(d::Distribution{Univariate, Continuous}, q::Real)
if q < 0
TooSmall()
elseif q > 1
TooBig()
else
quantile(d, q)
end
end
The return type is Union{Real, TooSmall, TooBig}. There’s no need for a Some here, because the “non-error” return value will always be of type Real—a “non-error” return value will never have type TooSmall or TooBig.
The larger question here is whether to use union types or sum types for return values. And as I’ve already mentioned, there are downsides to using sum types. The following talk by Rich Hickey about union vs sum types for return values might be of interest: