* Add total ConvertText alternative to Conv * Explain ConvertText's meaning * Rename convertText to toS for compatibility * 0.3.0 Refactor (#111) * Begin work on 0.3 refactor * Remove old docs folder * Fix dodgy exports * 4.8 constraint for null and length * Guards for Semigroup export for base<4.9 * Fix Data.Bits exports * Guards for typeable exports * Remove unused pragmas * Update hlint.yaml * Use liftM because of pre-AMP quirkk * Data.Char exports * Rework Exception exports * Fix bounds * Adding Monad.Fail shim * Fix displayException export * Explicit GHC.Prim import for ancient ghc * Explicit raise# for base-4.7 * Flush legacy testing infrastructure * Update git location * Update README * Add Partial module * Add concurrency exports * Explicit GHC.Float exports * Bounds for threadWaitReadSTM, threadWaitWriteSTM, forkOSWithUnmask * Fix for weird undocumented underflowError weirdness * forkOSWithUnask for base>4.8 * Fix GHC.Real exports pre base-4.7 * Fix withMVarMasked for base-4.7 * Update nix derivation * Update derivation * Update derivation * Explicit functor exports * <$ export * Overwrite binary * Fix some missing exports * Update Changelog * Minor export fixes base<4.9 * Explicit exports * Export handler * Generate export lists for multiple versions (#114) * Generate export lists for #112 * Make export lists format OccName uniformly * Make compile on ancient GHC * Use Foldable.concat * Hacks to make ghc-7.6 API happy * liftIO shim * Fix sortOn warning * Update ChangeLog * Update base bounds * Export conventions * Update Haddocks * Document GHC magic
138 lines
3.7 KiB
Haskell
138 lines
3.7 KiB
Haskell
{-# 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 test f val = if test val then Nothing else Just (f val)
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Head
|
|
-------------------------------------------------------------------------------
|
|
|
|
headMay :: [a] -> Maybe a
|
|
headMay = liftMay null head
|
|
|
|
headDef :: a -> [a] -> a
|
|
headDef def = fromMaybe def . headMay
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Init
|
|
-------------------------------------------------------------------------------
|
|
|
|
initMay :: [a] -> Maybe [a]
|
|
initMay = liftMay null init
|
|
|
|
initDef :: [a] -> [a] -> [a]
|
|
initDef def = fromMaybe def . initMay
|
|
|
|
initSafe :: [a] -> [a]
|
|
initSafe = initDef []
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Tail
|
|
-------------------------------------------------------------------------------
|
|
|
|
tailMay :: [a] -> Maybe [a]
|
|
tailMay = liftMay null tail
|
|
|
|
tailDef :: [a] -> [a] -> [a]
|
|
tailDef def = fromMaybe def . tailMay
|
|
|
|
tailSafe :: [a] -> [a]
|
|
tailSafe = tailDef []
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Last
|
|
-------------------------------------------------------------------------------
|
|
|
|
lastMay :: [a] -> Maybe a
|
|
lastMay = liftMay null last
|
|
|
|
lastDef :: a -> [a] -> a
|
|
lastDef def = fromMaybe def . lastMay
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Maximum
|
|
-------------------------------------------------------------------------------
|
|
|
|
minimumMay, maximumMay :: Ord a => [a] -> Maybe a
|
|
minimumMay = liftMay null minimum
|
|
maximumMay = liftMay null maximum
|
|
|
|
minimumDef, maximumDef :: Ord a => a -> [a] -> a
|
|
minimumDef def = fromMaybe def . minimumMay
|
|
maximumDef def = fromMaybe def . maximumMay
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Foldr
|
|
-------------------------------------------------------------------------------
|
|
|
|
foldr1May, foldl1May, foldl1May' :: (a -> a -> a) -> [a] -> Maybe a
|
|
foldr1May = liftMay null . foldr1
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Foldl
|
|
-------------------------------------------------------------------------------
|
|
|
|
foldl1May = liftMay null . foldl1
|
|
foldl1May' = liftMay null . foldl1'
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- At
|
|
-------------------------------------------------------------------------------
|
|
|
|
at_ :: [a] -> Int -> Either [Char] a
|
|
at_ ys o
|
|
| o < 0 = Left ("index must not be negative, index=" ++ show o)
|
|
| otherwise = f o ys
|
|
where
|
|
f 0 (x:_) = Right x
|
|
f i (_:xs) = f (i-1) xs
|
|
f i [] = Left ("index too large, index=" ++ show o ++ ", length=" ++ show (o-i))
|
|
|
|
atMay :: [a] -> Int -> Maybe a
|
|
atMay xs i = case xs `at_` i of
|
|
Left _ -> Nothing
|
|
Right val -> Just val
|
|
|
|
atDef :: a -> [a] -> Int -> a
|
|
atDef def xs i = case xs `at_` i of
|
|
Left _ -> def
|
|
Right val -> val
|