mixed-types-num-0.3: src/Numeric/CollectErrors.hs
{-|
Module : Numeric.CollectErrors
Description : A type of numeric errors to be collected
Copyright : (c) Michal Konecny
License : BSD3
Maintainer : mikkonecny@gmail.com
Stability : experimental
Portability : portable
A type of numeric errors to be collected.
-}
module Numeric.CollectErrors
(
-- * Type of numeric errors
ErrorCertaintyLevel(..), NumError(..), NumErrors, sample_NumErrors
-- * Specialisation to numeric errors
, CN
, hasCertainError, hasCertainErrorCN
, noValueCN
, noValueNumErrorCertainCN, noValueNumErrorPotentialCN
, getMaybeValueCN, getErrorsCN, prependErrorsCN
, CanEnsureCN, EnsureCN, EnsureNoCN
, ensureCN, deEnsureCN, ensureNoCN
, noValueECN, prependErrorsECN
, noValueNumErrorCertainECN, noValueNumErrorPotentialECN
, CanExtractCN, extractCN
-- ** More compact synonyms
, cn, deCN, (~!)
)
where
import Prelude
(Show(..), Eq(..), Bool, String, Maybe(..), Either(..), (++), (.), or, map, fst, ($))
import Control.CollectErrors
data NumError =
DivByZero | OutOfRange String | NumError String
deriving (Eq)
instance Show NumError where
show DivByZero = "division by 0"
show (OutOfRange s) = "out of range: " ++ s
show (NumError s) = "numeric error: " ++ s
data ErrorCertaintyLevel =
ErrorCertain | ErrorPotential
deriving (Eq)
instance Show ErrorCertaintyLevel where
show ErrorCertain = "ERROR"
show ErrorPotential = "POTENTIAL ERROR"
type NumErrors = [(ErrorCertaintyLevel, NumError)]
instance CanTestErrorsCertain NumErrors where
hasCertainError es =
or $ map ((== ErrorCertain) . fst) es
hasCertainErrorCN :: CN v -> Bool
hasCertainErrorCN = hasCertainErrorCE
sample_NumErrors :: Maybe [(ErrorCertaintyLevel, NumError)]
sample_NumErrors = Nothing
type CN = CollectErrors NumErrors
type CanEnsureCN = CanEnsureCE NumErrors
type EnsureCN a = EnsureCE NumErrors a
type EnsureNoCN a = EnsureNoCE NumErrors a
type CanExtractCN f = CanExtractCE NumErrors f
extractCN ::
(CanEnsureCN c, CanExtractCN f) =>
f c -> CN (f (EnsureNoCN c))
extractCN = extractCE sample_NumErrors
{-|
Translate a value of a type @a@
to a value of a type @CollectNumErrors a@ except when @a@
already is a @CollectNumErrors@ type, in which case the value is left as is.
-}
ensureCN :: (CanEnsureCN v) => v -> EnsureCN v
ensureCN = ensureCE sample_NumErrors
{-|
Translate a value of a type @EnsureCN es a@ to @a@,
throwing an exception if there was an error.
If @a@ is a @CollectNumErrors@ type, then this is just an identity.
-}
deEnsureCN :: (CanEnsureCN v) => EnsureCN v -> Either NumErrors v
deEnsureCN = deEnsureCE sample_NumErrors
{-|
Translate a value of a type @a@
to a value of a type @CollectNumErrors a@ except when @a@
already is a @CollectNumErrors@ type, in which case the value is left as is.
-}
ensureNoCN :: (CanEnsureCN v) => v -> (Maybe (EnsureNoCN v), NumErrors)
ensureNoCN = ensureNoCE sample_NumErrors
noValueECN :: (CanEnsureCN v) => Maybe v -> NumErrors -> EnsureCN v
noValueECN = noValueECE
prependErrorsECN :: (CanEnsureCN v) => Maybe v -> NumErrors -> EnsureCN v -> EnsureCN v
prependErrorsECN = prependErrorsECE
{-| Construct an empty wrapper indicating that given error has certainly occurred. -}
noValueNumErrorCertainECN :: (CanEnsureCN v) => Maybe v -> NumError -> EnsureCN v
noValueNumErrorCertainECN sample_v e = noValueECE sample_v [(ErrorCertain, e)]
{-| Construct an empty wrapper indicating that given error may have occurred. -}
noValueNumErrorPotentialECN :: (CanEnsureCN v) => Maybe v -> NumError -> EnsureCN v
noValueNumErrorPotentialECN sample_v e = noValueECE sample_v [(ErrorPotential, e)]
getErrorsCN :: CN v -> NumErrors
getErrorsCN = getErrorsCE
getMaybeValueCN :: CN v -> Maybe v
getMaybeValueCN = getMaybeValueCE
noValueCN :: NumErrors -> CN v
noValueCN = noValueCE
{-| Construct an empty wrapper indicating that given error has certainly occurred. -}
noValueNumErrorCertainCN :: NumError -> CN v
noValueNumErrorCertainCN e = noValueCN [(ErrorCertain, e)]
{-| Construct an empty wrapper indicating that given error may have occurred. -}
noValueNumErrorPotentialCN :: NumError -> CN v
noValueNumErrorPotentialCN e = noValueCN [(ErrorPotential, e)]
prependErrorsCN :: NumErrors -> CN v -> CN v
prependErrorsCN = prependErrorsCE
-- more compact synonyms:
{-| Wrap a value in the 'CollectNumErrors' wrapper. -}
cn :: (CanEnsureCN v) => v -> EnsureCN v
cn = ensureCN
{-| An unsafe way to get a value out of the CollectNumErrors wrapper. -}
deCN :: (CanEnsureCN v) => EnsureCN v -> Either NumErrors v
deCN = deEnsureCN
{-| An unsafe way to get a value out of the CollectNumErrors wrapper. -}
(~!) :: (CanEnsureCN v, Show v) => v -> EnsureNoCN v
(~!) = getValueOrThrowErrorsNCE sample_NumErrors