{-| This module extends the @safe@ library's functions with corresponding
    versions compatible with 'Either' and 'ExceptT', and also provides a few
    'Maybe'-compatible functions missing from @safe@.

    I suffix the 'Either'-compatible functions with @Err@ and prefix the
    'ExceptT'-compatible functions with @try@.

    Note that this library re-exports the 'Maybe' compatible functions from
    @safe@ in the "Control.Error" module, so they are not provided here.

    The \'@Z@\'-suffixed functions generalize the 'Maybe' functions to also work
    with anything that implements 'MonadPlus', including:

    * Lists

    * Most parsers

    * 'ExceptT' (if the left value is a 'Monoid')
-}

module Control.Error.Safe (
    -- * Maybe-compatible functions
    assertMay,
    rightMay,

    -- * Either-compatible functions
    tailErr,
    initErr,
    headErr,
    lastErr,
    minimumErr,
    maximumErr,
    foldr1Err,
    foldl1Err,
    foldl1Err',
    atErr,
    readErr,
    assertErr,
    justErr,

    -- * ExceptT-compatible functions
    tryTail,
    tryInit,
    tryHead,
    tryLast,
    tryMinimum,
    tryMaximum,
    tryFoldr1,
    tryFoldl1,
    tryFoldl1',
    tryAt,
    tryRead,
    tryAssert,
    tryJust,
    tryRight,

    -- * MonadPlus-compatible functions
    tailZ,
    initZ,
    headZ,
    lastZ,
    minimumZ,
    maximumZ,
    foldr1Z,
    foldl1Z,
    foldl1Z',
    atZ,
    readZ,
    assertZ,
    justZ,
    rightZ
    ) where

import Control.Error.Util (note, hoistEither)
import Control.Monad (MonadPlus(mzero))
import Control.Monad.Trans.Except (ExceptT)
import qualified Safe as S

-- | An assertion that fails in the 'Maybe' monad
assertMay :: Bool -> Maybe ()
assertMay :: Bool -> Maybe ()
assertMay = Bool -> Maybe ()
forall (m :: * -> *). MonadPlus m => Bool -> m ()
assertZ

-- | A 'fromRight' that fails in the 'Maybe' monad
rightMay :: Either e a -> Maybe a
rightMay :: forall e a. Either e a -> Maybe a
rightMay = Either e a -> Maybe a
forall (m :: * -> *) e a. MonadPlus m => Either e a -> m a
rightZ

-- | A 'tail' that fails in the 'Either' monad
tailErr :: e -> [a] -> Either e [a]
tailErr :: forall e a. e -> [a] -> Either e [a]
tailErr e
e = e -> Maybe [a] -> Either e [a]
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe [a] -> Either e [a])
-> ([a] -> Maybe [a]) -> [a] -> Either e [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe [a]
forall a. [a] -> Maybe [a]
S.tailMay

-- | An 'init' that fails in the 'Either' monad
initErr :: e -> [a] -> Either e [a]
initErr :: forall e a. e -> [a] -> Either e [a]
initErr e
e = e -> Maybe [a] -> Either e [a]
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe [a] -> Either e [a])
-> ([a] -> Maybe [a]) -> [a] -> Either e [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe [a]
forall a. [a] -> Maybe [a]
S.initMay

-- | A 'head' that fails in the 'Either' monad
headErr :: e -> [a] -> Either e a
headErr :: forall e a. e -> [a] -> Either e a
headErr e
e = e -> Maybe a -> Either e a
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe a -> Either e a) -> ([a] -> Maybe a) -> [a] -> Either e a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe a
forall a. [a] -> Maybe a
S.headMay

-- | A 'last' that fails in the 'Either' monad
lastErr :: e -> [a] -> Either e a
lastErr :: forall e a. e -> [a] -> Either e a
lastErr e
e = e -> Maybe a -> Either e a
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe a -> Either e a) -> ([a] -> Maybe a) -> [a] -> Either e a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe a
forall a. [a] -> Maybe a
S.lastMay

-- | A 'minimum' that fails in the 'Either' monad
minimumErr :: (Ord a) => e -> [a] -> Either e a
minimumErr :: forall a e. Ord a => e -> [a] -> Either e a
minimumErr e
e = e -> Maybe a -> Either e a
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe a -> Either e a) -> ([a] -> Maybe a) -> [a] -> Either e a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe a
forall a. Ord a => [a] -> Maybe a
S.minimumMay

-- | A 'maximum' that fails in the 'Either' monad
maximumErr :: (Ord a) => e -> [a] -> Either e a
maximumErr :: forall a e. Ord a => e -> [a] -> Either e a
maximumErr e
e = e -> Maybe a -> Either e a
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe a -> Either e a) -> ([a] -> Maybe a) -> [a] -> Either e a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe a
forall a. Ord a => [a] -> Maybe a
S.maximumMay

-- | A 'foldr1' that fails in the 'Either' monad
foldr1Err :: e -> (a -> a -> a) -> [a] -> Either e a
foldr1Err :: forall e a. e -> (a -> a -> a) -> [a] -> Either e a
foldr1Err e
e a -> a -> a
step [a]
xs = e -> Maybe a -> Either e a
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe a -> Either e a) -> Maybe a -> Either e a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> [a] -> Maybe a
forall a. (a -> a -> a) -> [a] -> Maybe a
S.foldr1May a -> a -> a
step [a]
xs

-- | A 'foldl1' that fails in the 'Either' monad
foldl1Err :: e -> (a -> a -> a) -> [a] -> Either e a
foldl1Err :: forall e a. e -> (a -> a -> a) -> [a] -> Either e a
foldl1Err e
e a -> a -> a
step [a]
xs = e -> Maybe a -> Either e a
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe a -> Either e a) -> Maybe a -> Either e a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> [a] -> Maybe a
forall a. (a -> a -> a) -> [a] -> Maybe a
S.foldl1May a -> a -> a
step [a]
xs

-- | A 'foldl1'' that fails in the 'Either' monad
foldl1Err' :: e -> (a -> a -> a) -> [a] -> Either e a
foldl1Err' :: forall e a. e -> (a -> a -> a) -> [a] -> Either e a
foldl1Err' e
e a -> a -> a
step [a]
xs = e -> Maybe a -> Either e a
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe a -> Either e a) -> Maybe a -> Either e a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> [a] -> Maybe a
forall a. (a -> a -> a) -> [a] -> Maybe a
S.foldl1May' a -> a -> a
step [a]
xs

-- | A ('!!') that fails in the 'Either' monad
atErr :: e -> [a] -> Int -> Either e a
atErr :: forall e a. e -> [a] -> Int -> Either e a
atErr e
e [a]
xs Int
n = e -> Maybe a -> Either e a
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe a -> Either e a) -> Maybe a -> Either e a
forall a b. (a -> b) -> a -> b
$ [a] -> Int -> Maybe a
forall a. [a] -> Int -> Maybe a
S.atMay [a]
xs Int
n

-- | A 'read' that fails in the 'Either' monad
readErr :: (Read a) => e -> String -> Either e a
readErr :: forall a e. Read a => e -> String -> Either e a
readErr e
e = e -> Maybe a -> Either e a
forall a b. a -> Maybe b -> Either a b
note e
e (Maybe a -> Either e a)
-> (String -> Maybe a) -> String -> Either e a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe a
forall a. Read a => String -> Maybe a
S.readMay

-- | An assertion that fails in the 'Either' monad
assertErr :: e -> Bool -> Either e ()
assertErr :: forall e. e -> Bool -> Either e ()
assertErr e
e Bool
p = if Bool
p then () -> Either e ()
forall a b. b -> Either a b
Right () else e -> Either e ()
forall a b. a -> Either a b
Left e
e

-- | A 'fromJust' that fails in the 'Either' monad
justErr :: e -> Maybe a -> Either e a
justErr :: forall a b. a -> Maybe b -> Either a b
justErr e
e = Either e a -> (a -> Either e a) -> Maybe a -> Either e a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (e -> Either e a
forall a b. a -> Either a b
Left e
e) a -> Either e a
forall a b. b -> Either a b
Right

-- | A 'tail' that fails in the 'ExceptT' monad
tryTail :: (Monad m) => e -> [a] -> ExceptT e m [a]
tryTail :: forall (m :: * -> *) e a. Monad m => e -> [a] -> ExceptT e m [a]
tryTail e
e [a]
xs = Either e [a] -> ExceptT e m [a]
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e [a] -> ExceptT e m [a])
-> Either e [a] -> ExceptT e m [a]
forall a b. (a -> b) -> a -> b
$ e -> [a] -> Either e [a]
forall e a. e -> [a] -> Either e [a]
tailErr e
e [a]
xs

-- | An 'init' that fails in the 'ExceptT' monad
tryInit :: (Monad m) => e -> [a] -> ExceptT e m [a]
tryInit :: forall (m :: * -> *) e a. Monad m => e -> [a] -> ExceptT e m [a]
tryInit e
e [a]
xs = Either e [a] -> ExceptT e m [a]
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e [a] -> ExceptT e m [a])
-> Either e [a] -> ExceptT e m [a]
forall a b. (a -> b) -> a -> b
$ e -> [a] -> Either e [a]
forall e a. e -> [a] -> Either e [a]
initErr e
e [a]
xs

-- | A 'head' that fails in the 'ExceptT' monad
tryHead :: (Monad m) => e -> [a] -> ExceptT e m a
tryHead :: forall (m :: * -> *) e a. Monad m => e -> [a] -> ExceptT e m a
tryHead e
e [a]
xs = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ e -> [a] -> Either e a
forall e a. e -> [a] -> Either e a
headErr e
e [a]
xs

-- | A 'last' that fails in the 'ExceptT' monad
tryLast :: (Monad m) => e -> [a] -> ExceptT e m a
tryLast :: forall (m :: * -> *) e a. Monad m => e -> [a] -> ExceptT e m a
tryLast e
e [a]
xs = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ e -> [a] -> Either e a
forall e a. e -> [a] -> Either e a
lastErr e
e [a]
xs

-- | A 'minimum' that fails in the 'ExceptT' monad
tryMinimum :: (Monad m, Ord a) => e -> [a] -> ExceptT e m a
tryMinimum :: forall (m :: * -> *) a e.
(Monad m, Ord a) =>
e -> [a] -> ExceptT e m a
tryMinimum e
e [a]
xs = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ e -> [a] -> Either e a
forall a e. Ord a => e -> [a] -> Either e a
maximumErr e
e [a]
xs

-- | A 'maximum' that fails in the 'ExceptT' monad
tryMaximum :: (Monad m, Ord a) => e -> [a] -> ExceptT e m a
tryMaximum :: forall (m :: * -> *) a e.
(Monad m, Ord a) =>
e -> [a] -> ExceptT e m a
tryMaximum e
e [a]
xs = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ e -> [a] -> Either e a
forall a e. Ord a => e -> [a] -> Either e a
maximumErr e
e [a]
xs

-- | A 'foldr1' that fails in the 'ExceptT' monad
tryFoldr1 :: (Monad m) => e -> (a -> a -> a) -> [a] -> ExceptT e m a
tryFoldr1 :: forall (m :: * -> *) e a.
Monad m =>
e -> (a -> a -> a) -> [a] -> ExceptT e m a
tryFoldr1 e
e a -> a -> a
step [a]
xs = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ e -> (a -> a -> a) -> [a] -> Either e a
forall e a. e -> (a -> a -> a) -> [a] -> Either e a
foldr1Err e
e a -> a -> a
step [a]
xs

-- | A 'foldl1' that fails in the 'ExceptT' monad
tryFoldl1 :: (Monad m) => e -> (a -> a -> a) -> [a] -> ExceptT e m a
tryFoldl1 :: forall (m :: * -> *) e a.
Monad m =>
e -> (a -> a -> a) -> [a] -> ExceptT e m a
tryFoldl1 e
e a -> a -> a
step [a]
xs = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ e -> (a -> a -> a) -> [a] -> Either e a
forall e a. e -> (a -> a -> a) -> [a] -> Either e a
foldl1Err e
e a -> a -> a
step [a]
xs

-- | A 'foldl1'' that fails in the 'ExceptT' monad
tryFoldl1' :: (Monad m) => e -> (a -> a -> a) -> [a] -> ExceptT e m a
tryFoldl1' :: forall (m :: * -> *) e a.
Monad m =>
e -> (a -> a -> a) -> [a] -> ExceptT e m a
tryFoldl1' e
e a -> a -> a
step [a]
xs = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ e -> (a -> a -> a) -> [a] -> Either e a
forall e a. e -> (a -> a -> a) -> [a] -> Either e a
foldl1Err' e
e a -> a -> a
step [a]
xs

-- | A ('!!') that fails in the 'ExceptT' monad
tryAt :: (Monad m) => e -> [a] -> Int -> ExceptT e m a
tryAt :: forall (m :: * -> *) e a.
Monad m =>
e -> [a] -> Int -> ExceptT e m a
tryAt e
e [a]
xs Int
n = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ e -> [a] -> Int -> Either e a
forall e a. e -> [a] -> Int -> Either e a
atErr e
e [a]
xs Int
n

-- | A 'read' that fails in the 'ExceptT' monad
tryRead :: (Monad m, Read a) => e -> String -> ExceptT e m a
tryRead :: forall (m :: * -> *) a e.
(Monad m, Read a) =>
e -> String -> ExceptT e m a
tryRead e
e String
str = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ e -> String -> Either e a
forall a e. Read a => e -> String -> Either e a
readErr e
e String
str

-- | An assertion that fails in the 'ExceptT' monad
tryAssert :: (Monad m) => e -> Bool -> ExceptT e m ()
tryAssert :: forall (m :: * -> *) e. Monad m => e -> Bool -> ExceptT e m ()
tryAssert e
e Bool
p = Either e () -> ExceptT e m ()
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e () -> ExceptT e m ()) -> Either e () -> ExceptT e m ()
forall a b. (a -> b) -> a -> b
$ e -> Bool -> Either e ()
forall e. e -> Bool -> Either e ()
assertErr e
e Bool
p

-- | A 'fromJust' that fails in the 'ExceptT' monad
tryJust :: (Monad m) => e -> Maybe a -> ExceptT e m a
tryJust :: forall (m :: * -> *) e a. Monad m => e -> Maybe a -> ExceptT e m a
tryJust e
e Maybe a
m = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ e -> Maybe a -> Either e a
forall a b. a -> Maybe b -> Either a b
justErr e
e Maybe a
m

-- | A 'fromRight' that fails in the 'ExceptT' monad
tryRight :: (Monad m) => Either e a -> ExceptT e m a
tryRight :: forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
tryRight = Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
hoistEither

-- | A 'tail' that fails using 'mzero'
tailZ :: (MonadPlus m) => [a] -> m [a]
tailZ :: forall (m :: * -> *) a. MonadPlus m => [a] -> m [a]
tailZ = m [a] -> ([a] -> m [a]) -> Maybe [a] -> m [a]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m [a]
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero [a] -> m [a]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe [a] -> m [a]) -> ([a] -> Maybe [a]) -> [a] -> m [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe [a]
forall a. [a] -> Maybe [a]
S.tailMay

-- | An 'init' that fails using 'mzero'
initZ :: (MonadPlus m) => [a] -> m [a]
initZ :: forall (m :: * -> *) a. MonadPlus m => [a] -> m [a]
initZ = m [a] -> ([a] -> m [a]) -> Maybe [a] -> m [a]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m [a]
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero [a] -> m [a]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe [a] -> m [a]) -> ([a] -> Maybe [a]) -> [a] -> m [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe [a]
forall a. [a] -> Maybe [a]
S.initMay

-- | A 'head' that fails using 'mzero'
headZ :: (MonadPlus m) => [a] -> m a
headZ :: forall (m :: * -> *) a. MonadPlus m => [a] -> m a
headZ = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m a) -> ([a] -> Maybe a) -> [a] -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe a
forall a. [a] -> Maybe a
S.headMay

-- | A 'last' that fails using 'mzero'
lastZ :: (MonadPlus m) => [a] -> m a
lastZ :: forall (m :: * -> *) a. MonadPlus m => [a] -> m a
lastZ = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m a) -> ([a] -> Maybe a) -> [a] -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe a
forall a. [a] -> Maybe a
S.lastMay

-- | A 'minimum' that fails using 'mzero'
minimumZ :: (MonadPlus m) => (Ord a) => [a] -> m a
minimumZ :: forall (m :: * -> *) a. (MonadPlus m, Ord a) => [a] -> m a
minimumZ = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m a) -> ([a] -> Maybe a) -> [a] -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe a
forall a. Ord a => [a] -> Maybe a
S.minimumMay

-- | A 'maximum' that fails using 'mzero'
maximumZ :: (MonadPlus m) => (Ord a) => [a] -> m a
maximumZ :: forall (m :: * -> *) a. (MonadPlus m, Ord a) => [a] -> m a
maximumZ = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m a) -> ([a] -> Maybe a) -> [a] -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Maybe a
forall a. Ord a => [a] -> Maybe a
S.maximumMay

-- | A 'foldr1' that fails using 'mzero'
foldr1Z :: (MonadPlus m) => (a -> a -> a) -> [a] -> m a
foldr1Z :: forall (m :: * -> *) a. MonadPlus m => (a -> a -> a) -> [a] -> m a
foldr1Z a -> a -> a
step [a]
xs = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m a) -> Maybe a -> m a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> [a] -> Maybe a
forall a. (a -> a -> a) -> [a] -> Maybe a
S.foldr1May a -> a -> a
step [a]
xs

-- | A 'foldl1' that fails using 'mzero'
foldl1Z :: (MonadPlus m) => (a -> a -> a) -> [a] -> m a
foldl1Z :: forall (m :: * -> *) a. MonadPlus m => (a -> a -> a) -> [a] -> m a
foldl1Z a -> a -> a
step [a]
xs = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m a) -> Maybe a -> m a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> [a] -> Maybe a
forall a. (a -> a -> a) -> [a] -> Maybe a
S.foldl1May a -> a -> a
step [a]
xs

-- | A 'foldl1'' that fails using 'mzero'
foldl1Z' :: (MonadPlus m) => (a -> a -> a) -> [a] -> m a
foldl1Z' :: forall (m :: * -> *) a. MonadPlus m => (a -> a -> a) -> [a] -> m a
foldl1Z' a -> a -> a
step [a]
xs = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m a) -> Maybe a -> m a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> [a] -> Maybe a
forall a. (a -> a -> a) -> [a] -> Maybe a
S.foldl1May' a -> a -> a
step [a]
xs

-- | A ('!!') that fails using 'mzero'
atZ :: (MonadPlus m) => [a] -> Int -> m a
atZ :: forall (m :: * -> *) a. MonadPlus m => [a] -> Int -> m a
atZ [a]
xs Int
n = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m a) -> Maybe a -> m a
forall a b. (a -> b) -> a -> b
$ [a] -> Int -> Maybe a
forall a. [a] -> Int -> Maybe a
S.atMay [a]
xs Int
n

-- | A 'read' that fails using 'mzero'
readZ :: (MonadPlus m) => (Read a) => String -> m a
readZ :: forall (m :: * -> *) a. (MonadPlus m, Read a) => String -> m a
readZ = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m a) -> (String -> Maybe a) -> String -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe a
forall a. Read a => String -> Maybe a
S.readMay

-- | An assertion that fails using 'mzero'
assertZ :: (MonadPlus m) => Bool -> m ()
assertZ :: forall (m :: * -> *). MonadPlus m => Bool -> m ()
assertZ Bool
p = if Bool
p then () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return () else m ()
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero

-- | A 'fromJust' that fails using 'mzero'
justZ :: (MonadPlus m) => Maybe a -> m a
justZ :: forall (m :: * -> *) a. MonadPlus m => Maybe a -> m a
justZ = m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return

-- | A 'fromRight' that fails using 'mzero'
rightZ :: (MonadPlus m) => Either e a -> m a
rightZ :: forall (m :: * -> *) e a. MonadPlus m => Either e a -> m a
rightZ = (e -> m a) -> (a -> m a) -> Either e a -> m a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (m a -> e -> m a
forall a b. a -> b -> a
const m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero) a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return