module Data.List.Safe where import Data.Bifunctor (first) -- | Analogous to 'Data.List.last', but returns 'Nothing' on an empty list, instead of throwing an error. safeLast :: [a] -> Maybe a safeLast [] = Nothing safeLast l = Just $ last l -- | Analogous to `Data.List.head`, but returns 'Nothing' in case of an empty list. safeHead :: [a] -> Maybe a safeHead [] = Nothing safeHead (x : _) = Just x -- | Analogous tu 'Data.List.!!', but does not throw an error on missing index. safeIndex :: Int -> [a] -> Maybe a safeIndex _ [] = Nothing safeIndex 0 (x : _) = Just x safeIndex n (_ : xs) | n < 0 = Nothing | otherwise = safeIndex (n - 1) xs -- | Safely deconstructs a list from the end. -- -- More efficient than @(init x, last x)@ safeUnsnoc :: [a] -> Maybe ([a], a) safeUnsnoc [] = Nothing safeUnsnoc [x] = Just ([], x) safeUnsnoc (x : xs) = first (x :) <$> safeUnsnoc xs -- | Safely deconstructs a list from the beginning, returning 'Nothing' if the list is empty. safeUncons :: [a] -> Maybe (a, [a]) safeUncons [] = Nothing safeUncons (x : xs) = Just (x, xs)