{-# LANGUAGE CPP #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Protolude.Safe (
    headMay
  , headDef
  , initMay
  , initDef
  , initSafe
  , tailMay
  , tailDef
  , tailSafe
  , lastDef
  , lastMay
  , foldr1May
  , foldl1May
  , foldl1May'
  , maximumMay
  , minimumMay
  , maximumDef
  , minimumDef
  , atMay
  , atDef
) where


import Data.Ord (Ord, (<))
import Data.Int (Int)
import Data.Char (Char)
import Data.Bool (Bool, otherwise)
import Data.Maybe (Maybe(Nothing, Just), fromMaybe)
import Data.Either (Either(Left, Right))
import Data.Function ((.))
import Data.List (null, head, last, tail, init, maximum, minimum, foldr1, foldl1, foldl1', (++))

import GHC.Num ((-))
import GHC.Show (show)

liftMay :: (a -> Bool) -> (a -> b) -> (a -> Maybe b)
liftMay :: forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
liftMay a -> Bool
test a -> b
f a
val = if a -> Bool
test a
val then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (a -> b
f a
val)

-------------------------------------------------------------------------------
-- Head
-------------------------------------------------------------------------------

headMay :: [a] -> Maybe a
headMay :: forall a. [a] -> Maybe a
headMay = forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
liftMay forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall a. [a] -> a
head

headDef :: a -> [a] -> a
headDef :: forall a. a -> [a] -> a
headDef a
def = forall a. a -> Maybe a -> a
fromMaybe a
def forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe a
headMay

-------------------------------------------------------------------------------
-- Init
-------------------------------------------------------------------------------

initMay :: [a] -> Maybe [a]
initMay :: forall a. [a] -> Maybe [a]
initMay = forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
liftMay forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall a. [a] -> [a]
init

initDef :: [a] -> [a] -> [a]
initDef :: forall a. [a] -> [a] -> [a]
initDef [a]
def = forall a. a -> Maybe a -> a
fromMaybe [a]
def forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe [a]
initMay

initSafe :: [a] -> [a]
initSafe :: forall a. [a] -> [a]
initSafe = forall a. [a] -> [a] -> [a]
initDef []

-------------------------------------------------------------------------------
-- Tail
-------------------------------------------------------------------------------

tailMay :: [a] -> Maybe [a]
tailMay :: forall a. [a] -> Maybe [a]
tailMay = forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
liftMay forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall a. [a] -> [a]
tail

tailDef :: [a] -> [a] -> [a]
tailDef :: forall a. [a] -> [a] -> [a]
tailDef [a]
def = forall a. a -> Maybe a -> a
fromMaybe [a]
def forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe [a]
tailMay

tailSafe :: [a] -> [a]
tailSafe :: forall a. [a] -> [a]
tailSafe = forall a. [a] -> [a] -> [a]
tailDef []

-------------------------------------------------------------------------------
-- Last
-------------------------------------------------------------------------------

lastMay :: [a] -> Maybe a
lastMay :: forall a. [a] -> Maybe a
lastMay = forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
liftMay forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall a. [a] -> a
last

lastDef :: a -> [a] -> a
lastDef :: forall a. a -> [a] -> a
lastDef a
def = forall a. a -> Maybe a -> a
fromMaybe a
def forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe a
lastMay

-------------------------------------------------------------------------------
-- Maximum
-------------------------------------------------------------------------------

minimumMay, maximumMay :: Ord a => [a] -> Maybe a
minimumMay :: forall a. Ord a => [a] -> Maybe a
minimumMay = forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
liftMay forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum
maximumMay :: forall a. Ord a => [a] -> Maybe a
maximumMay = forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
liftMay forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum

minimumDef, maximumDef :: Ord a => a -> [a] -> a
minimumDef :: forall a. Ord a => a -> [a] -> a
minimumDef a
def = forall a. a -> Maybe a -> a
fromMaybe a
def forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => [a] -> Maybe a
minimumMay
maximumDef :: forall a. Ord a => a -> [a] -> a
maximumDef a
def = forall a. a -> Maybe a -> a
fromMaybe a
def forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => [a] -> Maybe a
maximumMay

-------------------------------------------------------------------------------
-- Foldr
-------------------------------------------------------------------------------

foldr1May, foldl1May, foldl1May' :: (a -> a -> a) -> [a] -> Maybe a
foldr1May :: forall a. (a -> a -> a) -> [a] -> Maybe a
foldr1May = forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
liftMay forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1

-------------------------------------------------------------------------------
-- Foldl
-------------------------------------------------------------------------------

foldl1May :: forall a. (a -> a -> a) -> [a] -> Maybe a
foldl1May = forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
liftMay forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1
foldl1May' :: forall a. (a -> a -> a) -> [a] -> Maybe a
foldl1May' = forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
liftMay forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a -> a) -> [a] -> a
foldl1'

-------------------------------------------------------------------------------
-- At
-------------------------------------------------------------------------------

at_ :: [a] -> Int -> Either [Char] a
at_ :: forall a. [a] -> Int -> Either [Char] a
at_ [a]
ys Int
o
  | Int
o forall a. Ord a => a -> a -> Bool
< Int
0 = forall a b. a -> Either a b
Left ([Char]
"index must not be negative, index=" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show Int
o)
  | Bool
otherwise = forall {b}. Int -> [b] -> Either [Char] b
f Int
o [a]
ys
  where
    f :: Int -> [b] -> Either [Char] b
f Int
0 (b
x:[b]
_) = forall a b. b -> Either a b
Right b
x
    f Int
i (b
_:[b]
xs) = Int -> [b] -> Either [Char] b
f (Int
iforall a. Num a => a -> a -> a
-Int
1) [b]
xs
    f Int
i [] = forall a b. a -> Either a b
Left ([Char]
"index too large, index=" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show Int
o forall a. [a] -> [a] -> [a]
++ [Char]
", length=" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show (Int
oforall a. Num a => a -> a -> a
-Int
i))

atMay :: [a] -> Int -> Maybe a
atMay :: forall a. [a] -> Int -> Maybe a
atMay [a]
xs Int
i = case [a]
xs forall a. [a] -> Int -> Either [Char] a
`at_` Int
i of
  Left [Char]
_  -> forall a. Maybe a
Nothing
  Right a
val -> forall a. a -> Maybe a
Just a
val

atDef :: a -> [a] -> Int -> a
atDef :: forall a. a -> [a] -> Int -> a
atDef a
def [a]
xs Int
i = case [a]
xs forall a. [a] -> Int -> Either [Char] a
`at_` Int
i of
  Left [Char]
_  -> a
def
  Right a
val -> a
val