{-# OPTIONS_HADDOCK hide #-}

-- |
-- Copyright: © 2018-2024 Intersect MBO
-- License: Apache-2.0
--
-- Provides internal functions relating to verification of invariants.
--
module Internal.Invariant
    ( invariant
    ) where

import Prelude

-- | Checks whether or not an invariant holds, by applying the given predicate
--   to the given value.
--
-- If the invariant does not hold (indicated by the predicate function
-- returning 'False'), throws an error with the specified message.
--
-- >>> invariant "not empty" [1,2,3] (not . null)
-- [1, 2, 3]
--
-- >>> invariant "not empty" [] (not . null)
-- *** Exception: not empty
invariant
    :: String
        -- ^ The message
    -> a
        -- ^ The value to test
    -> (a -> Bool)
        -- ^ The predicate
    -> a
invariant :: forall a. String -> a -> (a -> Bool) -> a
invariant String
msg a
a a -> Bool
predicate =
    if a -> Bool
predicate a
a then a
a else String -> a
forall a. HasCallStack => String -> a
error String
msg