packages feed

Kawaii-Parser-4.0.0: Parser/Utilities.hs

{-|
Description: Assorted utilities.

* Assorted utilities.
-}
module Parser.Utilities (
  (<->),
  all_equal,
  between,
  check,
  construct_map,
  construct_set,
  lcm_all) where
  import Control.Monad.Except
  import Data.Foldable as Foldable
  import Data.Map as Map
  import Data.Set as Set
  -- | Concatenate strings with a whitespace in between.
  infixr 5 <->
  (<->) :: String -> String -> String
  s <-> t = s <> " " <> t
  -- | Checks if all elements of a list are equal. Returns @Nothing@ if all elements aren't equal, @Just Nothing@ if the list is
  -- empty and @Just (Just x)@ if all elements are equal to @x@.
  all_equal :: Eq t => [t] -> Maybe (Maybe t)
  all_equal x =
    case x of
      [] -> Just Nothing
      y : x' ->
        do
          check () (all ((==) y) x')
          Just (Just y)
  -- | Check if the value is in bounds.
  between :: Ord t => t -> t -> t -> Bool
  between lowest highest x = lowest <= x && highest >= x
  -- | Throw an error if the condition is not satisfied.
  check :: MonadError error f => error -> Bool -> f ()
  check err condition =
    case condition of
      False -> throwError err
      True -> return ()
  -- | Construct a map if all keys are different. Otherwise return @Nothing@.
  construct_map :: Ord t => [(t, u)] -> Maybe (Map t u)
  construct_map x =
    do
      let y = Map.fromList x
      check () (Foldable.length x == Map.size y)
      Just y
  -- | Construct a set if all elements are different. Otherwise return @Nothing@.
  construct_set :: Ord t => [t] -> Maybe (Set t)
  construct_set x =
    do
      let y = Set.fromList x
      check () (Foldable.length x == Set.size y)
      Just y
{-
  -- | Safe list indexation.
  element_at :: Int -> [t] -> Maybe t
  element_at j x =
    do
      check () (between 0 (Foldable.length x - 1) j)
      return (x !! j)
-}
  -- | Aggregate least common denominator.
  lcm_all :: (Foldable f, Integral t) => f t -> t
  lcm_all = Foldable.foldr lcm 1
{-
  -- | Swap Left and Right.
  swap_either :: Either t u -> Either u t
  swap_either x =
    case x of
      Left y -> Right y
      Right y -> Left y
-}