packages feed

antelude-0.1.0: src/Antelude/Result.hs

{- |
Module      : Antelude.Result
Description : Contains some functions for Results.
Maintainer  : dneavesdev@pm.me
-}
module Antelude.Result
    ( Result (..)
    , errWithDefault
    , filterErrs
    , filterOks
    , fromEither
    , fromMaybe
    , isErr
    , isOk
    , mapErr
    , mapOk
    , okWithDefault
    , partition
    , result
    ) where

import safe           Antelude.Function              ( (.>) )
import safe           Antelude.Internal.TypesClasses
    ( Bool (..)
    , Either
    , List
    , Maybe
    , Result (..)
    )
import safe           Antelude.List                  ( foldl' )
import safe           Antelude.Tuple.Pair            ( first, second )

import safe           Prelude                        ( either, maybe, (++) )


-- | Convert a 'Either a b' to an 'Result a b'.
fromEither :: Either err ok -> Result err ok
fromEither = either Err Ok


-- | Convert a 'Maybe a' to an 'Result () a'.
fromMaybe :: Maybe ok -> Result () ok
fromMaybe = maybe (Err ()) Ok


-- | Map both cases of a 'Result a b' given two functions: one for the 'Err' case, and one for the 'Ok' case.
result :: (err -> a) -> (ok -> a) -> Result err ok -> a
result fnErr fnOk = \case
  Ok ok -> fnOk ok
  Err err -> fnErr err


-- | Map the 'Ok' case of a 'Result a b' given a function. Does not change an 'Err' case.
mapOk :: (ok -> newOk) -> Result err ok -> Result err newOk
mapOk fnOk = result Err (fnOk .> Ok)


-- | Map the 'Err' case of a 'Result a b' given a function. Does not change an 'Ok' case.
mapErr :: (err -> newErr) -> Result err ok -> Result newErr ok
mapErr fnErr = result (fnErr .> Err) Ok


-- | Test if the 'Result a b' is 'Ok'.
isOk :: Result err ok -> Bool
isOk = \case
  Ok _ -> True
  Err _ -> False


-- | Test if the 'Result a b' is 'Err'.
isErr :: Result err ok -> Bool
isErr = \case
  Ok _ -> False
  Err _ -> True


-- | Get the value of an 'Result a b', returns the 'Ok' value, or a default if 'Err'.
errWithDefault :: ok -> Result err ok -> ok
errWithDefault dflt = \case
  Ok ok -> ok
  Err _ -> dflt


-- | Get the value of an 'Result a b', returns the 'Err' value, or a default if 'Ok'.
okWithDefault :: err -> Result err ok -> err
okWithDefault dflt = \case
  Ok _ -> dflt
  Err err -> err


-- | Take a 'List' of 'Result err ok' and create a Tuple with 'List err' and 'List ok'.
partition :: List (Result err ok) -> (List ok, List err)
partition =
  foldl'
    ( \acc res ->
        case res of
          Ok ok ->
            (first acc ++ [ok], second acc)
          Err err ->
            (first acc, second acc ++ [err])
    )
    ([], [])


-- | Take a 'List' of 'Result a b' and return a 'List' containing all of the values from the 'Ok' cases.
filterOks :: List (Result err ok) -> List ok
filterOks = partition .> first


-- | Take a 'List' of 'Result a b' and return a 'List' containing all of the values from the 'Err' cases.
filterErrs :: List (Result err ok) -> List err
filterErrs = partition .> second