-- |
-- Module      : Streamly.Internal.Control.Exception
-- Copyright   : (c) 2019 Composewell Technologies
--
-- License     : BSD3
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC
--
-- Additional "Control.Exception" utilities.

module Streamly.Internal.Control.Exception
    ( assertM
    , verify
    , verifyM
    )
where

import Control.Exception (assert)

-- Like 'assert' but returns @()@ in an 'Applicative' context so that it can be
-- used as an independent statement in a @do@ block.
--
-- /Pre-release/
--
{-# INLINE assertM #-}
assertM :: Applicative f => Bool -> f ()
assertM :: Bool -> f ()
assertM Bool
predicate = Bool -> f () -> f ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
predicate (() -> f ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())

-- | Like 'assert' but is not removed by the compiler, it is always present in
-- production code.
--
-- /Pre-release/
--
{-# INLINE verify #-}
verify :: Bool -> a -> a
verify :: Bool -> a -> a
verify Bool
predicate a
val =
    if Bool
predicate
    -- XXX it would be nice if we can print the predicate expr.
    then [Char] -> a
forall a. (?callStack::CallStack) => [Char] -> a
error [Char]
"verify failed"
    else a
val

-- Like 'verify' but returns @()@ in an 'Applicative' context so that it can be
-- used as an independent statement in a @do@ block.
--
-- /Pre-release/
--
{-# INLINE verifyM #-}
verifyM :: Applicative f => Bool -> f ()
verifyM :: Bool -> f ()
verifyM Bool
predicate = Bool -> f () -> f ()
forall a. Bool -> a -> a
verify Bool
predicate (() -> f ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())