I was playing around Maybe and Either monad types (Chaining, applying conditional functions according to returned value, also returning error message which chained function has failed etc.). So it seemes to me like we can achieve same and more things that Maybe does by using Either monad. So my question is where the practical or conceptual difference between those ?
monads are used to address the more general problem of computations (involving state, input/output, backtracking, ...) returning values: they do not solve any input/output-problems directly but rather provide an elegant and flexible abstraction of many solutions to related problems.
The Maybe monad represents computations which might "go wrong" by not returning a value.
In Error handling we have two possible paths either a computation succeeds or fails. The imperative way to control the flow is using exceptions and a try/catch block.
Strictly speaking, Either cannot be a monad, as it has kind Type -> Type -> Type ; Either String can be (and is), because it has kind Type -> Type .
You are of course right that Maybe a
is isomorphic to Either Unit a
. The thing is that they are often semantically used to denote different things, a bit like the difference between returning null
and throwing a NoSuchElementException
:
Nothing
/None
denotes the "expected" missing of something, whileLeft e
denotes an error in getting it, for whatever reason.That said, we might even combine the two to something like:
query :: Either DBError (Maybe String)
where we express both the possibility of a missing value (a DB NULL
) and an error in the connection, the DBMS, or whatever (not saying that there aren't better designs, but you get the point).
Sometimes, the border is fluid; for saveHead :: [a] -> Maybe a
, we could say that the expected possibility of the error is encoded in the intent of the function, while something like saveDivide
might be encoded as Float -> Float -> Either FPError Float
or Float -> Float -> Maybe Float
, depending on the use case (again, just some stupid examples...).
If in doubt, the best option is probably to use a custom result ADT with semantic encoding (like data QueryResult = Success String | Null | Failure DBError
), and to prefer Maybe
to simple cases where it is "traditionally expected" (a subjective point, which however will be mostly OK if you gain experience).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With