packages feed

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 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