Safe Haskell | None |
---|---|
Language | Haskell2010 |
A Result
is the result of a computation that may fail. This is a great
way to manage errors in Elm, but we when using this package in Haskell we
tend to rely on Task
a lot too for error handling.
Synopsis
- data Result error value
- map :: (a -> value) -> Result x a -> Result x value
- map2 :: (a -> b -> value) -> Result x a -> Result x b -> Result x value
- map3 :: (a -> b -> c -> value) -> Result x a -> Result x b -> Result x c -> Result x value
- map4 :: (a -> b -> c -> d -> value) -> Result x a -> Result x b -> Result x c -> Result x d -> Result x value
- map5 :: (a -> b -> c -> d -> e -> value) -> Result x a -> Result x b -> Result x c -> Result x d -> Result x e -> Result x value
- andThen :: (a -> Result c b) -> Result c a -> Result c b
- withDefault :: a -> Result b a -> a
- toMaybe :: Result a b -> Maybe b
- fromMaybe :: a -> Maybe b -> Result a b
- mapError :: (a -> b) -> Result a c -> Result b c
Type and Constructors
data Result error value Source #
A Result
is either Ok
meaning the computation succeeded, or it is an
Err
meaning that there was some failure.
Mapping
map :: (a -> value) -> Result x a -> Result x value Source #
Apply a function to a result. If the result is Ok
, it will be converted.
If the result is an Err
, the same error value will propagate through.
map sqrt (Ok 4.0) == Ok 2.0 map sqrt (Err "bad input") == Err "bad input"
map2 :: (a -> b -> value) -> Result x a -> Result x b -> Result x value Source #
Apply a function if both results are Ok
. If not, the first Err
will
propagate through.
map2 max (Ok 42) (Ok 13) == Ok 42 map2 max (Err "x") (Ok 13) == Err "x" map2 max (Ok 42) (Err "y") == Err "y" map2 max (Err "x") (Err "y") == Err "x"
This can be useful if you have two computations that may fail, and you want to put them together quickly.
map4 :: (a -> b -> c -> d -> value) -> Result x a -> Result x b -> Result x c -> Result x d -> Result x value Source #
map5 :: (a -> b -> c -> d -> e -> value) -> Result x a -> Result x b -> Result x c -> Result x d -> Result x e -> Result x value Source #
Chaining
andThen :: (a -> Result c b) -> Result c a -> Result c b Source #
Chain together a sequence of computations that may fail. It is helpful to see its definition:
andThen : (a -> Result e b) -> Result e a -> Result e b andThen callback result = case result of Ok value -> callback value Err msg -> Err msg
This means we only continue with the callback if things are going well. For
example, say you need to use (toInt : String -> Result String Int
) to parse
a month and make sure it is between 1 and 12:
toValidMonth : Int -> Result String Int toValidMonth month = if month >= 1 && month <= 12 then Ok month else Err "months must be between 1 and 12"
toMonth : String -> Result String Int toMonth rawString = toInt rawString |> andThen toValidMonth
-- toMonth "4" == Ok 4 -- toMonth "9" == Ok 9 -- toMonth "a" == Err "cannot parse to an Int" -- toMonth "0" == Err "months must be between 1 and 12"
This allows us to come out of a chain of operations with quite a specific error message. It is often best to create a custom type that explicitly represents the exact ways your computation may fail. This way it is easy to handle in your code.
Handling Errors
withDefault :: a -> Result b a -> a Source #
If the result is Ok
return the value, but if the result is an Err
then
return a given default value. The following examples try to parse integers.
Result.withDefault 0 (Ok 123) == 123 Result.withDefault 0 (Err "no") == 0
toMaybe :: Result a b -> Maybe b Source #
Convert to a simpler Maybe
if the actual error message is not needed or
you need to interact with some code that primarily uses maybes.
parseInt : String -> Result ParseError Int maybeParseInt : String -> Maybe Int maybeParseInt string = toMaybe (parseInt string)
fromMaybe :: a -> Maybe b -> Result a b Source #
Convert from a simple Maybe
to interact with some code that primarily
uses Results
.
parseInt : String -> Maybe Int resultParseInt : String -> Result String Int resultParseInt string = fromMaybe ("error parsing string: " ++ toString string) (parseInt string)
mapError :: (a -> b) -> Result a c -> Result b c Source #
Transform an Err
value. For example, say the errors we get have too much
information:
parseInt : String -> Result ParseError Int type alias ParseError = { message : String , code : Int , position : (Int,Int) } mapError .message (parseInt "123") == Ok 123 mapError .message (parseInt "abc") == Err "char 'a' is not a number"