{- |
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 :: forall err ok. Either err ok -> Result err ok
fromEither = (err -> Result err ok)
-> (ok -> Result err ok) -> Either err ok -> Result err ok
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either err -> Result err ok
forall err ok. err -> Result err ok
Err ok -> Result err ok
forall err ok. ok -> Result err ok
Ok


-- | Convert a 'Maybe a' to an 'Result () a'.
fromMaybe :: Maybe ok -> Result () ok
fromMaybe :: forall ok. Maybe ok -> Result () ok
fromMaybe = Result () ok -> (ok -> Result () ok) -> Maybe ok -> Result () ok
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> Result () ok
forall err ok. err -> Result err ok
Err ()) ok -> Result () ok
forall err ok. ok -> Result err ok
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 :: forall err a ok. (err -> a) -> (ok -> a) -> Result err ok -> a
result err -> a
fnErr ok -> a
fnOk = \case
  Ok ok
ok -> ok -> a
fnOk ok
ok
  Err err
err -> err -> a
fnErr err
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 :: forall ok newOk err.
(ok -> newOk) -> Result err ok -> Result err newOk
mapOk ok -> newOk
fnOk = (err -> Result err newOk)
-> (ok -> Result err newOk) -> Result err ok -> Result err newOk
forall err a ok. (err -> a) -> (ok -> a) -> Result err ok -> a
result err -> Result err newOk
forall err ok. err -> Result err ok
Err (ok -> newOk
fnOk (ok -> newOk)
-> (newOk -> Result err newOk) -> ok -> Result err newOk
forall a b c. (a -> b) -> (b -> c) -> a -> c
.> newOk -> Result err newOk
forall err ok. ok -> Result err ok
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 :: forall err newErr ok.
(err -> newErr) -> Result err ok -> Result newErr ok
mapErr err -> newErr
fnErr = (err -> Result newErr ok)
-> (ok -> Result newErr ok) -> Result err ok -> Result newErr ok
forall err a ok. (err -> a) -> (ok -> a) -> Result err ok -> a
result (err -> newErr
fnErr (err -> newErr)
-> (newErr -> Result newErr ok) -> err -> Result newErr ok
forall a b c. (a -> b) -> (b -> c) -> a -> c
.> newErr -> Result newErr ok
forall err ok. err -> Result err ok
Err) ok -> Result newErr ok
forall err ok. ok -> Result err ok
Ok


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


-- | Test if the 'Result a b' is 'Err'.
isErr :: Result err ok -> Bool
isErr :: forall err ok. Result err ok -> Bool
isErr = \case
  Ok ok
_ -> Bool
False
  Err err
_ -> Bool
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 :: forall ok err. ok -> Result err ok -> ok
errWithDefault ok
dflt = \case
  Ok ok
ok -> ok
ok
  Err err
_ -> ok
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 :: forall err ok. err -> Result err ok -> err
okWithDefault err
dflt = \case
  Ok ok
_ -> err
dflt
  Err err
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 :: forall err ok. List (Result err ok) -> (List ok, List err)
partition =
  ((List ok, List err) -> Result err ok -> (List ok, List err))
-> (List ok, List err) -> [Result err ok] -> (List ok, List err)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl'
    ( \(List ok, List err)
acc Result err ok
res ->
        case Result err ok
res of
          Ok ok
ok ->
            ((List ok, List err) -> List ok
forall a b. Pair a b -> a
first (List ok, List err)
acc List ok -> List ok -> List ok
forall a. [a] -> [a] -> [a]
++ [ok
ok], (List ok, List err) -> List err
forall a b. Pair a b -> b
second (List ok, List err)
acc)
          Err err
err ->
            ((List ok, List err) -> List ok
forall a b. Pair a b -> a
first (List ok, List err)
acc, (List ok, List err) -> List err
forall a b. Pair a b -> b
second (List ok, List err)
acc List err -> List err -> List err
forall a. [a] -> [a] -> [a]
++ [err
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 :: forall err ok. List (Result err ok) -> List ok
filterOks = List (Result err ok) -> (List ok, List err)
forall err ok. List (Result err ok) -> (List ok, List err)
partition (List (Result err ok) -> (List ok, List err))
-> ((List ok, List err) -> List ok)
-> List (Result err ok)
-> List ok
forall a b c. (a -> b) -> (b -> c) -> a -> c
.> (List ok, List err) -> List ok
forall a b. Pair a b -> a
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 :: forall err ok. List (Result err ok) -> List err
filterErrs = List (Result err ok) -> (List ok, List err)
forall err ok. List (Result err ok) -> (List ok, List err)
partition (List (Result err ok) -> (List ok, List err))
-> ((List ok, List err) -> List err)
-> List (Result err ok)
-> List err
forall a b c. (a -> b) -> (b -> c) -> a -> c
.> (List ok, List err) -> List err
forall a b. Pair a b -> b
second