collect-errors (empty) → 0.1.0.0
raw patch · 11 files changed
+607/−0 lines, 11 filesdep +QuickCheckdep +basedep +containerssetup-changed
Dependencies added: QuickCheck, base, containers
Files
- ChangeLog.md +11/−0
- LICENSE +30/−0
- README.md +35/−0
- Setup.hs +2/−0
- collect-errors.cabal +47/−0
- src/Control/CollectErrors.hs +32/−0
- src/Control/CollectErrors/PreludeInstances.hs +64/−0
- src/Control/CollectErrors/Type.hs +203/−0
- src/Numeric/CollectErrors.hs +34/−0
- src/Numeric/CollectErrors/PreludeInstances.hs +74/−0
- src/Numeric/CollectErrors/Type.hs +75/−0
+ ChangeLog.md view
@@ -0,0 +1,11 @@+# Changelog for collect-errors++## v0.1.0.0++* Initial port of CollectErrors and CN from mixed-types-num-0.4.2++* Simplify the code by abandoning EnsureCE and related type functions and utilities++* NumErrors within CN are now a set to prevent multiple occurrences of the same error++* Add CollectError or CN instances for various Prelude type classes, including Num and Floating, checking for domain violations
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Michal Konecny (c) 2021++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Author name here nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,35 @@+# collect-errors++`CollectErrors es t` is a monad wrapper around values of type `t` which can accommodate (a list of)+(potential) errors of type `es` that have (maybe) occurred during the computation+of a value. A value may be missing, leaving only the error(s).++The wrapper `CN t` is a special case of `CollectErrors es t` with `es` = `NumErrors`.++The `CN` wrapper also propagates instances of `Floating`,+allowing us to write expressions with partial+functions (ie functions that fail for some inputs) instead of+branching after each application of such function:++ *Numeric.CollectErrors> a = 1 :: CN Double+ *Numeric.CollectErrors> (1/(a-1))+(sqrt (a-2))+ {{ERROR: division by 0; ERROR: out of domain: sqrt for negative arg -1.0}}++as opposed to:++ *Prelude> a = 1 :: Double+ *Prelude> (1/(a-1))+(sqrt (a-2))+ NaN++Dealing with the errors can be moved outside the expression:++ *Numeric.CollectErrors> a = 1 :: CN Double+ *Numeric.CollectErrors> toEither $ 1/(a-1)+ Left {ERROR: division by 0}++ *Numeric.CollectErrors> toEither $ 1/a+(sqrt a)+ Right 2.0++The `CN` wrapper has support for **potential errors** so that it can be applied to a set arithmetic such as **interval arithmetic**.++The `Floating` instance cannot be used with a set arithmetic since the instance relies on true/false comparisons but a set arithmetic has only **three-valued (true/false/undecided) comparisons**. Package [mixed-types-num](https://hackage.haskell.org/package/mixed-types-num) provides alternative numerical type classes in which three-valued (ie Kleenean) comparisons are available.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ collect-errors.cabal view
@@ -0,0 +1,47 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.33.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: 7bf0425f189848e2370d0cab1f8335a5386e11e6f03271d1faafe460c97204ff++name: collect-errors+version: 0.1.0.0+synopsis: Error monad with a Float instance+description: Please see the README on GitHub at <https://github.com/michalkonecny/collect-errors#readme>+category: Math+homepage: https://github.com/michalkonecny/collect-errors#readme+bug-reports: https://github.com/michalkonecny/collect-errors/issues+author: Michal Konecny+maintainer: mikkonecny@gmail.com+copyright: 2021 Michal Konecny+license: BSD3+license-file: LICENSE+build-type: Simple+extra-source-files:+ README.md+ ChangeLog.md++source-repository head+ type: git+ location: https://github.com/michalkonecny/collect-errors++library+ exposed-modules:+ Control.CollectErrors+ Control.CollectErrors.PreludeInstances+ Control.CollectErrors.Type+ Numeric.CollectErrors+ Numeric.CollectErrors.PreludeInstances+ Numeric.CollectErrors.Type+ other-modules:+ Paths_collect_errors+ hs-source-dirs:+ src+ ghc-options: -Wall+ build-depends:+ QuickCheck >=2.7+ , base >=4.7 && <5+ , containers+ default-language: Haskell2010
+ src/Control/CollectErrors.hs view
@@ -0,0 +1,32 @@+module Control.CollectErrors+(+-- * Monad for collecting errors in expressions+ CollectErrors(..)+, CanBeErrors+, CanTestErrorsCertain(..)+, CanTestErrorsPresent(..)+-- ** Utilities+, noValue+, prependErrors+, unCollectErrors+, (~!)+, toEither+, withErrorOrValue+, filterValuesWithoutError+, lift+, liftCE+, liftPair+, lift2+, lift2CE+, lift1T+, liftT1+, lift1TCE+, liftT1CE+, lift2pair+, lift1Tpair+, liftT1pair+)+where++import Control.CollectErrors.Type+import Control.CollectErrors.PreludeInstances ()
+ src/Control/CollectErrors/PreludeInstances.hs view
@@ -0,0 +1,64 @@+module Control.CollectErrors.PreludeInstances where++import Prelude++import Text.Printf ( printf )++import Control.CollectErrors.Type+ ( CollectErrors(CollectErrors), CanBeErrors, lift, lift2 )+++instance (CanBeErrors es, Eq v) => Eq (CollectErrors es v) where+ (==) = liftGotValues2 "(==)" (==)++instance (CanBeErrors es, Ord v) => Ord (CollectErrors es v) where+ compare = liftGotValues2 "compare" compare+ (<) = liftGotValues2 "(<)" (<)+ (<=) = liftGotValues2 "(<=)" (<=)+ (>) = liftGotValues2 "(>)" (>)+ (>=) = liftGotValues2 "(>=)" (>=)+ max = lift2 max+ min = lift2 min++instance (CanBeErrors es, Bounded v) => Bounded (CollectErrors es v) where+ minBound = pure minBound+ maxBound = pure maxBound++instance (CanBeErrors es, Enum v) => Enum (CollectErrors es v) where+ toEnum = pure . toEnum+ fromEnum = liftGotValue "fromEnum" fromEnum++instance (CanBeErrors es, Num v) => Num (CollectErrors es v) where+ fromInteger = pure . fromInteger+ (+) = lift2 (+)+ (-) = lift2 (-)+ (*) = lift2 (*)+ abs = lift abs+ negate = lift negate+ signum = lift signum++instance (CanBeErrors es, Real v) => Real (CollectErrors es v) where+ toRational = liftGotValue "toRational" toRational+++{- Utilities -}++errorMissingValue :: (Show t, Monoid t) => String -> t -> t2+errorMissingValue label es = + error $ printf "Missing value in %s: %s" label (show es)++errorMissingValues :: (Show t, Monoid t) => String -> [t] -> t2+errorMissingValues label ess = + error $ printf "Missing value(s) in %s: %s" label (show $ mconcat ess)++liftGotValue :: (CanBeErrors es) => String -> (t1 -> t) -> CollectErrors es t1 -> t+liftGotValue _ op (CollectErrors (Just v1) _) = + op v1+liftGotValue label op (CollectErrors _ es1) = + errorMissingValue label es1++liftGotValues2 :: (CanBeErrors es) => String -> (t1 -> t2 -> t) -> CollectErrors es t1 -> CollectErrors es t2 -> t+liftGotValues2 _ op (CollectErrors (Just v1) _) (CollectErrors (Just v2) _) = + op v1 v2+liftGotValues2 label op (CollectErrors _ es1) (CollectErrors _ es2) = + errorMissingValues label [es1, es2]
+ src/Control/CollectErrors/Type.hs view
@@ -0,0 +1,203 @@+{-# LANGUAGE ConstraintKinds #-}+module Control.CollectErrors.Type where++import Prelude++import Control.Applicative ( Applicative(liftA2), liftA )++import qualified Data.Set as Set++import Test.QuickCheck ( Arbitrary(arbitrary) )++import Text.Printf ( printf )++{-|+ A wrapper around values which can accommodate a list of+ (potential) errors that have (maybe) occurred during the computation+ of a value. A value may be missing, leaving only the error(s).++ Such error collection allows one to write expressions with partial+ functions (ie functions that fail for some inputs) instead of+ branching after each application of such function.+ Dealing with the errors can be moved outside the expression.+ If the error data contain enough information, their list can be used+ to trace the source of the errors.+-}+data CollectErrors es v =+ CollectErrors+ { getMaybeValue :: Maybe v+ , getErrors :: es }++class CanTestErrorsCertain es where+ hasCertainError :: es -> Bool++instance (CanTestErrorsCertain es) => CanTestErrorsCertain (CollectErrors es v) where+ hasCertainError (CollectErrors _ es) = hasCertainError es++instance (CanTestErrorsCertain es) => CanTestErrorsCertain [es] where+ hasCertainError = or . map hasCertainError++instance (CanTestErrorsCertain es) => CanTestErrorsCertain (Set.Set es) where+ hasCertainError = or . map hasCertainError . Set.toList++class CanTestErrorsPresent es where+ hasError :: es -> Bool++instance (CanTestErrorsPresent es) => CanTestErrorsPresent (CollectErrors es v) where+ hasError (CollectErrors _ es) = hasError es++instance CanTestErrorsPresent [es] where+ hasError = not . null++instance CanTestErrorsPresent (Set.Set es) where+ hasError = not . null++type CanBeErrors es = (Monoid es, Eq es, Show es, CanTestErrorsCertain es, CanTestErrorsPresent es)++instance (Show v, CanBeErrors es) => (Show (CollectErrors es v)) where+ show (CollectErrors mv es) =+ case mv of+ Just v | es == mempty -> show v+ Just v -> printf "%s{%s}" (show v) (show es)+ Nothing -> printf "{%s}" (show es)++noValue :: es -> CollectErrors es v+noValue es = CollectErrors Nothing es++prependErrors :: (Monoid es) => es -> CollectErrors es v -> CollectErrors es v+prependErrors es1 (CollectErrors mv es2) = CollectErrors mv (es1 <> es2)++{-| Unsafe way to get a value out of the CollectErrors wrapper. -}+unCollectErrors :: Show es => CollectErrors es p -> p+unCollectErrors (CollectErrors (Just v) _) = v+unCollectErrors (CollectErrors _ es) = error $ "CollectErrors: " ++ show es++{-| Unsafe way to get a value out of the CollectErrors wrapper. -}+(~!) :: Show es => CollectErrors es p -> p+(~!) = unCollectErrors++{-| A safe way to get a value out of the CollectErrors wrapper. -}+toEither ::+ (CanBeErrors es)+ =>+ CollectErrors es v -> Either es v+toEither (CollectErrors mv es) =+ case mv of+ Just v | es == mempty -> Right v+ _ -> Left es++withErrorOrValue :: + (CanBeErrors es)+ =>+ (es -> t) -> (v -> t) -> CollectErrors es v -> t+withErrorOrValue onError onValue (CollectErrors mv es) =+ case mv of+ Just v | es == mempty -> onValue v+ _ -> onError es++filterValuesWithoutError ::+ (CanBeErrors es)+ =>+ [CollectErrors es v] -> [v]+filterValuesWithoutError [] = []+filterValuesWithoutError (vCE : rest) =+ withErrorOrValue (const restDone) (: restDone) vCE+ where+ restDone = filterValuesWithoutError rest++++-- functor instances:++instance Functor (CollectErrors es) where+ fmap f (CollectErrors mv es) =+ CollectErrors (fmap f mv) es++instance (Monoid es) => Applicative (CollectErrors es) where+ pure v = CollectErrors (Just v) mempty+ (CollectErrors (Just a) ae) <*> (CollectErrors (Just b) be) =+ CollectErrors (Just (a b)) (ae <> be)+ (CollectErrors _ ae) <*> (CollectErrors _ be) =+ CollectErrors Nothing (ae <> be)++lift :: (Monoid es) => (a -> b) -> (CollectErrors es a) -> (CollectErrors es b)+lift = liftA++liftCE :: (Monoid es) => (a -> (CollectErrors es c)) -> (CollectErrors es a) -> (CollectErrors es c)+liftCE f (CollectErrors (Just a) ae) =+ prependErrors ae $ f a+liftCE _ (CollectErrors _ ae) =+ CollectErrors Nothing ae++liftPair :: (Monoid es) => (a -> (c,d)) -> (CollectErrors es a) -> (CollectErrors es c, CollectErrors es d)+liftPair f (CollectErrors (Just a) ae) = + (CollectErrors (Just c) ae, CollectErrors (Just d) ae)+ where+ (c,d) = f a+liftPair _ (CollectErrors _ ae) = + (CollectErrors Nothing ae, CollectErrors Nothing ae)++lift2 :: (Monoid es) => (a -> b -> c) -> (CollectErrors es a) -> (CollectErrors es b) -> (CollectErrors es c)+lift2 = liftA2++lift2CE :: (Monoid es) => (a -> b -> (CollectErrors es c)) -> (CollectErrors es a) -> (CollectErrors es b) -> (CollectErrors es c)+lift2CE f (CollectErrors (Just a) ae) (CollectErrors (Just b) be) =+ prependErrors (ae <> be) $ f a b+lift2CE _ (CollectErrors _ ae) (CollectErrors _ be) =+ CollectErrors Nothing (ae <> be)++lift1T :: (Monoid es) => (a -> b -> c) -> (CollectErrors es a) -> b -> (CollectErrors es c)+lift1T fn (CollectErrors (Just a) ae) b = CollectErrors (Just (fn a b)) ae+lift1T _ (CollectErrors _ ae) _ = CollectErrors Nothing ae++lift1TCE :: (Monoid es) => (a -> b -> (CollectErrors es c)) -> (CollectErrors es a) -> b -> (CollectErrors es c)+lift1TCE fn (CollectErrors (Just a) ae) b = prependErrors ae $ fn a b+lift1TCE _ (CollectErrors _ ae) _ = CollectErrors Nothing ae++liftT1 :: (Monoid es) => (a -> b -> c) -> a -> (CollectErrors es b) -> (CollectErrors es c)+liftT1 fn a (CollectErrors (Just b) be) = CollectErrors (Just (fn a b)) be+liftT1 _ _ (CollectErrors _ be) = CollectErrors Nothing be++liftT1CE :: (Monoid es) => (a -> b -> (CollectErrors es c)) -> a -> (CollectErrors es b) -> (CollectErrors es c)+liftT1CE fn a (CollectErrors (Just b) be) = prependErrors be $ fn a b+liftT1CE _ _ (CollectErrors _ be) = CollectErrors Nothing be++lift2pair :: (Monoid es) => (a -> b -> (c,d)) -> (CollectErrors es a) -> (CollectErrors es b) -> (CollectErrors es c, CollectErrors es d)+lift2pair f (CollectErrors (Just a) ae) (CollectErrors (Just b) be) = + (CollectErrors (Just c) abe, CollectErrors (Just d) abe)+ where+ (c,d) = f a b+ abe = ae <> be+lift2pair _ (CollectErrors _ ae) (CollectErrors _ be) = + (CollectErrors Nothing abe, CollectErrors Nothing abe)+ where+ abe = ae <> be++lift1Tpair :: (Monoid es) => (a -> b -> (c,d)) -> (CollectErrors es a) -> b -> (CollectErrors es c, CollectErrors es d)+lift1Tpair f (CollectErrors (Just a) ae) b = + (CollectErrors (Just c) ae, CollectErrors (Just d) ae)+ where+ (c,d) = f a b+lift1Tpair _ (CollectErrors _ ae) _ = + (CollectErrors Nothing ae, CollectErrors Nothing ae)++liftT1pair :: (Monoid es) => (a -> b -> (c,d)) -> a -> (CollectErrors es b) -> (CollectErrors es c, CollectErrors es d)+liftT1pair f a (CollectErrors (Just b) be) = + (CollectErrors (Just c) be, CollectErrors (Just d) be)+ where+ (c,d) = f a b+liftT1pair _ _ (CollectErrors _ be) = + (CollectErrors Nothing be, CollectErrors Nothing be)++instance (Monoid es) => Monad (CollectErrors es) where+ ae >>= f =+ case ae of+ CollectErrors (Just a) es1 ->+ let (CollectErrors mv es2) = f a in+ CollectErrors mv (es1 <> es2)+ CollectErrors _ es ->+ CollectErrors Nothing es++instance (Arbitrary t, Monoid es) => Arbitrary (CollectErrors es t) where+ arbitrary = (\v -> CollectErrors (Just v) mempty) <$> arbitrary+
+ src/Numeric/CollectErrors.hs view
@@ -0,0 +1,34 @@+module Numeric.CollectErrors+(+ -- * Type of numeric errors+ NumError(..), ErrorCertaintyLevel(..), NumErrors, CN, cn, unCN, (~!)+ -- * Utilities+, noValueNumErrorCertain, noValueNumErrorPotential+ -- ** Applicable general collect-error utilities+, noValue+, prependErrors+, prependErrorCertain+, prependErrorPotential+, CanTestErrorsCertain(..)+, CanTestErrorsPresent(..)+, toEither+, withErrorOrValue+, filterValuesWithoutError+, lift+, liftCN+, liftPair+, lift2+, lift2CN+, lift1T+, liftT1+, lift1TCN+, liftT1CN+, lift2pair+, lift1Tpair+, liftT1pair+)+where++import Control.CollectErrors+import Numeric.CollectErrors.Type+import Numeric.CollectErrors.PreludeInstances ()
+ src/Numeric/CollectErrors/PreludeInstances.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+module Numeric.CollectErrors.PreludeInstances where++import Prelude++import Control.CollectErrors ( CollectErrors(CollectErrors), lift, lift2 )+import Control.CollectErrors.PreludeInstances ( liftGotValue )+import Numeric.CollectErrors.Type++instance (Fractional v, Eq v) => Fractional (CN v) where+ fromRational = pure . fromRational+ recip = liftAcheck (==0) (\_ -> DivByZero) recip+ (/) = liftA2checkB (==0) (\_ -> DivByZero) (/)++instance (Integral v, Ord v, Show v) => Integral (CN v) where+ quotRem (CollectErrors (Just a) ae) (CollectErrors (Just b) be) + | b <= 0 = (e,e)+ | otherwise = (CollectErrors (Just q) es, CollectErrors (Just r) es)+ where+ (q,r) = quotRem a b+ es = ae <> be+ e = noValueNumErrorCertain (OutOfDomain $ "quotRem with non-positive denominator " ++ show b)+ quotRem (CollectErrors _ ae) (CollectErrors _ be) = (e,e)+ where+ e = CollectErrors Nothing (ae <> be)+ toInteger = liftGotValue "toInteger" toInteger++instance (Floating v, Ord v, Show v) => Floating (CN v) where+ pi = pure pi+ exp = lift exp+ log = liftAcheckPositive "log" log+ sqrt = liftAcheckNonnegative "sqrt" sqrt+ (**) = lift2 (**) -- TODO: domain check+ logBase = lift2 logBase -- TODO: domain check+ sin = lift sin+ cos = lift cos+ asin = liftAcheckPlusMinusOne "asin" asin+ acos = liftAcheckPlusMinusOne "acos" acos+ atan = lift atan+ sinh = lift sinh+ cosh = lift cosh+ asinh = lift asinh+ acosh = lift acosh+ atanh = lift atanh++liftAcheck :: + (a -> Bool) -> + (a -> NumError) -> + (a -> v) -> CN a -> CN v+liftAcheck check err op aCN@(CollectErrors (Just a) _)+ | check a = noValueNumErrorCertain (err a)+liftAcheck _ _ op aCN = lift op aCN++liftAcheckPositive :: (Ord a, Num a, Show a) => String -> (a -> v) -> CN a -> CN v+liftAcheckPositive fnName =+ liftAcheck (<=0) (\x -> OutOfDomain $ fnName ++ " for non-positive arg " ++ show x)++liftAcheckNonnegative :: (Ord a, Num a, Show a) => String -> (a -> v) -> CN a -> CN v+liftAcheckNonnegative fnName =+ liftAcheck (<0) (\x -> OutOfDomain $ fnName ++ " for negative arg " ++ show x)++liftAcheckPlusMinusOne :: (Ord a, Num a, Show a) => String -> (a -> v) -> CN a -> CN v+liftAcheckPlusMinusOne fnName =+ liftAcheck (\x -> -1 <= x && x <= 1) (\x -> OutOfDomain $ fnName ++ " for illegal arg " ++ show x)++liftA2checkB :: + (b -> Bool) -> + (b -> NumError) -> + (a -> b -> v) -> + CN a -> CN b -> CN v+liftA2checkB checkB errB op a bCN@(CollectErrors (Just b) _)+ | checkB b = noValueNumErrorCertain (errB b)+liftA2checkB _ _ op a bCN = lift2 op a bCN
+ src/Numeric/CollectErrors/Type.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Numeric.CollectErrors.Type ++where++import qualified Data.List as List+import qualified Data.Set as Set++import Control.CollectErrors+ ( CanTestErrorsCertain(..), CollectErrors, noValue, prependErrors, liftCE, lift2CE, lift1TCE, liftT1CE, unCollectErrors, CanTestErrorsPresent )++cn :: v -> CN v+cn = pure++unCN :: CN p -> p+unCN = unCollectErrors++type CN = CollectErrors NumErrors+newtype NumErrors = NumErrors (Set.Set NumErrorLevel)+ deriving (Eq,Semigroup, Monoid, CanTestErrorsCertain, CanTestErrorsPresent)+type NumErrorLevel = (NumError, ErrorCertaintyLevel)++instance Show NumErrors where+ show (NumErrors set) =+ "{" <> (List.intercalate "; " $ map showEL $ Set.toList set) <> "}"+ where+ showEL (e,l) =+ show l <> ": " <> show e++data NumError =+ DivByZero | OutOfDomain String | NumError String+ deriving (Eq, Ord)++instance Show NumError where+ show DivByZero = "division by 0"+ show (OutOfDomain s) = "out of domain: " ++ s+ show (NumError s) = "numeric error: " ++ s++data ErrorCertaintyLevel =+ ErrorCertain | ErrorPotential+ deriving (Eq, Ord)++instance Show ErrorCertaintyLevel where+ show ErrorCertain = "ERROR"+ show ErrorPotential = "POTENTIAL ERROR"++instance CanTestErrorsCertain NumErrorLevel where+ hasCertainError = (== ErrorCertain) . snd++{-| Construct an empty wrapper indicating that given error has certainly occurred. -}+noValueNumErrorCertain :: NumError -> CN v+noValueNumErrorCertain e = noValue $ NumErrors $ Set.singleton (e, ErrorCertain)++{-| Construct an empty wrapper indicating that given error may have occurred. -}+noValueNumErrorPotential :: NumError -> CN v+noValueNumErrorPotential e = noValue $ NumErrors $ Set.singleton (e, ErrorPotential)++prependErrorCertain :: NumError -> CN t -> CN t+prependErrorCertain e = prependErrors $ NumErrors $ Set.singleton (e, ErrorCertain)+ +prependErrorPotential :: NumError -> CN t -> CN t+prependErrorPotential e = prependErrors $ NumErrors $ Set.singleton (e, ErrorPotential)++liftCN :: (a -> (CN c)) -> (CN a) -> (CN c)+liftCN = liftCE++lift2CN :: (a -> b -> (CN c)) -> (CN a) -> (CN b) -> (CN c)+lift2CN = lift2CE++lift1TCN :: (a -> b -> (CN c)) -> (CN a) -> b -> (CN c)+lift1TCN = lift1TCE+liftT1CN :: (a -> b -> (CN c)) -> a -> (CN b) -> (CN c)+liftT1CN = liftT1CE