packages feed

mixed-types-num 0.4.1 → 0.5.0.0

raw patch · 25 files changed

+1033/−2234 lines, 25 filesdep +collect-errorsdep ~base

Dependencies added: collect-errors

Dependency ranges changed: base

Files

+ README.md view
@@ -0,0 +1,20 @@+# mixed-types-num++This package provides a version of Prelude where+unary and binary operations such as `not`, `+`, `==`+have their result type derived from the parameter type(s)+and thus supports mixed-type arithmetic and comparisons.++Partial operations such as division, sqrt and power+do not throw exceptions even when errors such as division by zero+occur.  Instead, these errors are propagated bottom-up in+a bespoke error-accumulating functor from package collect-errors.++This library (as well as collect-errors) arose while developing the+[AERN2](https://github.com/michalkonecny/aern2) library for interval and exact real computation.+Certain aspects are specifically tailored for interval or exact real arithmetics,+including three-valued numerical comparisons and distinguishing potential and certain errors.++See module [MixedTypesNumPrelude](https://hackage.haskell.org/package/mixed-types-num/docs/MixedTypesNumPrelude.html) for further documentation.++[Hackage page including Haddock](https://hackage.haskell.org/package/mixed-types-num)
changelog.md view
@@ -1,5 +1,9 @@ # mixed-types-num change log +* v 0.5.0 2021-04-13+  * use package collect-errors with a much simpler CN wrapper+  * replace Maybe Bool by Kleenean (a new type)+  * remove very long type constraints in specifications using PartialTypeSignatures * v 0.4.1 2021-01-21   * add hasErrorCE and hasErrorCN for testing if CE/CN values contain errors * v 0.4.0.2 2020-08-02
mixed-types-num.cabal view
@@ -1,120 +1,98 @@+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: 49afc3a2c4bc0e8c25dc926023d6d0ae68fbdfc1880e1e70d30403256ddb1f11+ name:           mixed-types-num-version:        0.4.1-cabal-version:  >= 1.10-build-type:     Simple-homepage:       https://github.com/michalkonecny/mixed-types-num+version:        0.5.0.0+synopsis:       Alternative Prelude with numeric and logic expressions typed bottom-up+description:    Please see the README on GitHub at <https://github.com/michalkonecny/mixed-types-num#readme>+category:       Math+homepage:       https://github.com/michalkonecny/mixed-types-num#readme+bug-reports:    https://github.com/michalkonecny/mixed-types-num/issues author:         Michal Konecny-maintainer:     Michal Konecny <mikkonecny@gmail.com>-copyright:      (c) 2015-2021 Michal Konecny+maintainer:     mikkonecny@gmail.com+copyright:      2015-2021 Michal Konecny license:        BSD3 license-file:   LICENSE-extra-source-files:  changelog.md-stability:      experimental-category:       Math-synopsis:       Alternative Prelude with numeric and logic expressions typed bottom-up-Description:-    This package provides a version of Prelude where-    unary and binary operations such as @not@, @+@, @==@-    have their result type derived from the parameter type(s)-    and thus supports mixed-type arithmetic and comparisons.-    .-    Partial operations such as division, sqrt and power-    do not throw exceptions even when errors such as division by zero-    occur.  Instead, these errors are propagated bottom-up in-    a bespoke error-accumulating functor.-    .-    This library is a by-product of developing the-    <https://github.com/michalkonecny/aern2 AERN2> library for interval and exact real computation.-    Certain aspects are specifically tailored for interval or exact real arithmetics,-    including three-valued numerical comparisons-    and distinguishing potential and certain errors.-    .-    See module "MixedTypesNumPrelude" for further documentation.-    .-    /Ghci 8.0.* fails when loading this package/ due to ghc bug <https://ghc.haskell.org/trac/ghc/ticket/13385#ticket 13385>.-    This bug does not affect ghci 7.10.3 and ghci 8.2.* and above.+build-type:     Simple+extra-source-files:+    README.md+    changelog.md  source-repository head-  type:     git-  location: https://github.com/mikkonecny/mixed-types-num+  type: git+  location: https://github.com/michalkonecny/mixed-types-num  library-  hs-source-dirs:  src-  ghc-options:     -Wall -fno-warn-orphans-  default-language: Haskell2010-  default-extensions:-    RebindableSyntax,-    PostfixOperators,-    ScopedTypeVariables,-    TypeFamilies,-    TypeOperators,-    ConstraintKinds,-    DefaultSignatures,-    MultiParamTypeClasses,-    FlexibleContexts,-    FlexibleInstances,-    UndecidableInstances-  other-extensions:-    TemplateHaskell+  exposed-modules:+      Data.Convertible.Base+      Data.Convertible.Instances.Num+      Data.Convertible.Utils+      MixedTypesNumPrelude+      Numeric.MixedTypes.AddSub+      Numeric.MixedTypes.Bool+      Numeric.MixedTypes.Complex+      Numeric.MixedTypes.Div+      Numeric.MixedTypes.Elementary+      Numeric.MixedTypes.Eq+      Numeric.MixedTypes.Field+      Numeric.MixedTypes.Kleenean+      Numeric.MixedTypes.Literals+      Numeric.MixedTypes.MinMaxAbs+      Numeric.MixedTypes.Ord+      Numeric.MixedTypes.Power+      Numeric.MixedTypes.PreludeHiding+      Numeric.MixedTypes.Reduce+      Numeric.MixedTypes.Ring+      Numeric.MixedTypes.Round+      Utils.Test.EnforceRange+      Utils.TH.DeclForTypes+  other-modules:+      Paths_mixed_types_num+  hs-source-dirs:+      src+  default-extensions: RebindableSyntax PostfixOperators ScopedTypeVariables TypeFamilies TypeOperators ConstraintKinds DefaultSignatures MultiParamTypeClasses FlexibleContexts FlexibleInstances UndecidableInstances+  other-extensions: TemplateHaskell+  ghc-options: -Wall   build-depends:-    base >= 4.8 && < 5-    -- , convertible >= 1.1.1.0-    , template-haskell+      QuickCheck >=2.7+    , base >=4.7 && <5+    , collect-errors ==0.1.*+    , hspec >=2.1+    , hspec-smallcheck >=0.3     , mtl-    , hspec >= 2.1-    , hspec-smallcheck >= 0.3-    , smallcheck >= 1.1-    , QuickCheck >= 2.7-  exposed-modules:-    Utils.TH.DeclForTypes-    Utils.Test.EnforceRange-    Data.Convertible.Base-    Data.Convertible.Utils-    Data.Convertible.Instances.Num-    Control.CollectErrors-    Numeric.CollectErrors-    Numeric.MixedTypes.PreludeHiding-    Numeric.MixedTypes.Literals-    Numeric.MixedTypes.Bool-    Numeric.MixedTypes.Eq-    Numeric.MixedTypes.Ord-    Numeric.MixedTypes.MinMaxAbs-    Numeric.MixedTypes.AddSub-    Numeric.MixedTypes.Round-    Numeric.MixedTypes.Ring-    Numeric.MixedTypes.Field-    Numeric.MixedTypes.Elementary-    Numeric.MixedTypes.Complex-    MixedTypesNumPrelude---test-suite spec-  type:-      exitcode-stdio-1.0-  ghc-options:-      -Wall+    , smallcheck >=1.1+    , template-haskell   default-language: Haskell2010-  default-extensions:-    RebindableSyntax,-    PostfixOperators,-    ScopedTypeVariables,-    FlexibleContexts++test-suite mixed-types-num-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Numeric.MixedTypes.AddSubSpec+      Numeric.MixedTypes.BoolSpec+      Numeric.MixedTypes.EqOrdSpec+      Numeric.MixedTypes.FieldSpec+      Numeric.MixedTypes.LiteralsSpec+      Numeric.MixedTypes.MinMaxAbsSpec+      Numeric.MixedTypes.RingSpec+      Numeric.MixedTypes.RoundSpec+      Paths_mixed_types_num   hs-source-dirs:       test-  main-is:-    Spec.hs-  other-modules:-    Numeric.MixedTypes.AddSubSpec-    Numeric.MixedTypes.BoolSpec-    Numeric.MixedTypes.EqOrdSpec-    Numeric.MixedTypes.FieldSpec-    Numeric.MixedTypes.LiteralsSpec-    Numeric.MixedTypes.MinMaxAbsSpec-    Numeric.MixedTypes.RingSpec-    Numeric.MixedTypes.RoundSpec+  default-extensions: RebindableSyntax PostfixOperators ScopedTypeVariables TypeFamilies TypeOperators ConstraintKinds DefaultSignatures MultiParamTypeClasses FlexibleContexts FlexibleInstances UndecidableInstances+  other-extensions: TemplateHaskell+  ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall   build-depends:-    base >= 4.8 && < 5+      QuickCheck >=2.7+    , base >=4.7 && <5+    , collect-errors ==0.1.*+    , hspec >=2.1+    , hspec-smallcheck >=0.3     , mixed-types-num-    , hspec >= 2.1-    , hspec-smallcheck >= 0.3-    , QuickCheck >= 2.7+    , smallcheck >=1.1+  default-language: Haskell2010
− src/Control/CollectErrors.hs
@@ -1,452 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}-module Control.CollectErrors-(--- * Monad for collecting errors in expressions-  CollectErrors(..), SuitableForCE-, CanTestErrorsCertain(..), hasCertainErrorCE-, CanTestErrorsPresent(..), hasErrorCE-, noValueCE, prependErrorsCE-, filterValuesWithoutErrorCE, getValueIfNoErrorCE-, ce2ConvertResult--- * Tools for avoiding @CollectErrors(CollectErrors t)@ and putting CE inside containers-, CanEnsureCE(..)-, getValueOrThrowErrorsNCE-, lift1CE, lift2CE, lift2TCE, lift2TLCE, lift3CE--- ** Tools for pulling errors out of structures-, CanExtractCE(..)-)-where--import Prelude-  (Functor(..), Applicative(..), Monad(..), (<$>), ($), (.)-  , error, const, flip, not, fst, snd, foldMap, (++)-  , Int, Integer, Rational, Double, Bool, Char-  , Maybe(..), Either(..)-  , Show(..), Eq(..)-  , Traversable(..))-import Text.Printf--import Control.Monad (join)--import Data.Monoid-import Data.Maybe (fromJust)---- import Data.Convertible-import Data.Convertible.Base-import Data.Typeable---- import Language.Haskell.TH--import Test.QuickCheck--{-|-  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-    { getMaybeValueCE :: Maybe v-    , getErrorsCE :: es }--class CanTestErrorsCertain es where-  hasCertainError :: es -> Bool--hasCertainErrorCE :: (CanTestErrorsCertain es) => (CollectErrors es v) -> Bool-hasCertainErrorCE (CollectErrors _ es) = hasCertainError es--class CanTestErrorsPresent es where-  hasError :: es -> Bool--hasErrorCE :: (CanTestErrorsPresent es) => (CollectErrors es v) -> Bool-hasErrorCE (CollectErrors _ es) = hasError es--type SuitableForCE es = (Monoid es, Eq es, Show es, CanTestErrorsCertain es)--instance (Show v, SuitableForCE 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)--noValueCE :: es -> CollectErrors es v-noValueCE es = CollectErrors Nothing es--prependErrorsCE :: (Monoid es) => es -> CollectErrors es v -> CollectErrors es v-prependErrorsCE es1 (CollectErrors mv es2) = CollectErrors mv (es1 <> es2)--ce2ConvertResult ::-  (Typeable t, Show t, SuitableForCE es)-  =>-  CollectErrors es t -> Either ConvertError t-ce2ConvertResult (CollectErrors mv es) =-  case mv of-    Just v | es == mempty -> Right v-    _ -> convError (show es) mv--{-| A safe way to get a value out of the CollectErrors wrapper. -}-getValueIfNoErrorCE ::-  (SuitableForCE es)-  =>-  CollectErrors es v -> (v -> t) -> (es -> t) -> t-getValueIfNoErrorCE (CollectErrors mv es) withValue withErrors =-  case mv of-    Just v | es == mempty -> withValue v-    _ -> withErrors es--filterValuesWithoutErrorCE ::-  (SuitableForCE es)-  =>-  [CollectErrors es v] -> [v]-filterValuesWithoutErrorCE [] = []-filterValuesWithoutErrorCE (vCE : rest) =-  getValueIfNoErrorCE vCE (: restDone) (const restDone)-  where-  restDone = filterValuesWithoutErrorCE 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)--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--{-|-  A mechanism for adding and removing CollectErrors-  to a type in a manner that depends on-  the shape of the type, especially whether-  it already has CollectErrors.--}-class-  (Monoid es-  , EnsureCE es (EnsureCE es a) ~ EnsureCE es a-  , EnsureCE es (EnsureNoCE es a) ~ EnsureCE es a-  , EnsureNoCE es (EnsureCE es a) ~ EnsureNoCE es a-  , EnsureNoCE es (EnsureNoCE es a) ~ EnsureNoCE es a)-  =>-  CanEnsureCE es a where-  {-|-    Add CollectErrors to a type except when the type already-    has CollectErrors in it.-  -}-  type EnsureCE es a-  type EnsureCE es a = CollectErrors es a -- default-  type EnsureNoCE es a-  type EnsureNoCE es a = a -- default--  {-|-    Translate a value of a type @a@-    to a value of a type @EnsureCE es a@.-  -}-  ensureCE ::-    Maybe es {-^ sample only -} ->-    a -> EnsureCE es a--  default ensureCE ::-    (EnsureCE es a ~ CollectErrors es a)-    =>-    Maybe es {-^ sample only -} ->-    a -> EnsureCE es a-  ensureCE _ = pure--  deEnsureCE ::-    Maybe es {-^ sample only -} ->-    EnsureCE es a -> Either es a--  default deEnsureCE ::-    (EnsureCE es a ~ CollectErrors es a, Eq es) =>-    Maybe es {-^ sample only -} ->-    EnsureCE es a -> Either es a-  deEnsureCE _ (CollectErrors mv es) =-    case mv of-      Just v | es == mempty -> Right v-      _ -> Left es--  ensureNoCE ::-    Maybe es {-^ sample only -} ->-    a -> (Maybe (EnsureNoCE es a), es)--  default ensureNoCE ::-    (EnsureNoCE es a ~ a, Eq es, Monoid es) =>-    Maybe es {-^ sample only -} ->-    a -> (Maybe (EnsureNoCE es a), es)-  ensureNoCE _ a = (Just a, mempty)--  {-|  Make CollectErrors record with no value, only errors. -}-  noValueECE ::-    Maybe a {-^ sample only -} ->-    es -> EnsureCE es a--  default noValueECE ::-    (EnsureCE es a ~ CollectErrors es a)-    =>-    Maybe a ->-    es -> EnsureCE es a-  noValueECE _ = noValueCE--  prependErrorsECE ::-    Maybe a ->-    es -> EnsureCE es a -> EnsureCE es a-  default prependErrorsECE ::-    (EnsureCE es a ~ CollectErrors es a)-    =>-    Maybe a ->-    es -> EnsureCE es a -> EnsureCE es a-  prependErrorsECE _ = prependErrorsCE---- instance for CollectErrors a:--instance-  (SuitableForCE es, CanEnsureCE es a)-  =>-  CanEnsureCE es (CollectErrors es a)-  where-  type EnsureCE es (CollectErrors es a) = EnsureCE es a-  type EnsureNoCE es (CollectErrors es a) = EnsureNoCE es a--  ensureCE sample_es (CollectErrors mv es) =-    case mv of-      Just v -> prependErrorsECE (Just v) es $ ensureCE sample_es v-      _ -> noValueECE mv es-  deEnsureCE sample_es vCE =-    case deEnsureCE sample_es vCE of-      Right v -> Right $ CollectErrors (Just v) mempty-      Left es -> Left es-  ensureNoCE sample_es (CollectErrors mv es) =-    case fmap (ensureNoCE sample_es) mv of-      Just (Just v, es2) -> (Just v, es2 <> es)-      Just (_, es2) -> (Nothing, es2 <> es)-      _ -> (Nothing, mempty)--  noValueECE sample_vCE es =-    noValueECE (join $ fmap getMaybeValueCE sample_vCE) es-  prependErrorsECE sample_vCE =-    prependErrorsECE (join $ fmap getMaybeValueCE sample_vCE)---- instances for ground types, using the default implementations:--instance (SuitableForCE es) => CanEnsureCE es Int-instance (SuitableForCE es) => CanEnsureCE es Integer-instance (SuitableForCE es) => CanEnsureCE es Rational-instance (SuitableForCE es) => CanEnsureCE es Double-instance (SuitableForCE es) => CanEnsureCE es Bool-instance (SuitableForCE es) => CanEnsureCE es Char-instance (SuitableForCE es) => CanEnsureCE es ()---- instance for Maybe a:--instance-  (SuitableForCE es, CanEnsureCE es a)-  =>-  CanEnsureCE es (Maybe a)-  where-  type EnsureCE es (Maybe a) = Maybe (EnsureCE es a)-  type EnsureNoCE es (Maybe a) = Maybe (EnsureNoCE es a)--  ensureCE sample_es = fmap (ensureCE sample_es)-  deEnsureCE sample_es (Just vCE) = fmap Just (deEnsureCE sample_es vCE)-  deEnsureCE _sample_es Nothing = Right Nothing-  ensureNoCE sample_es (Just vCE) =-    case ensureNoCE sample_es vCE of-      (Just v, es) -> (Just (Just v), es)-      (_, es) -> (Nothing, es)-  ensureNoCE _sample_es Nothing = (Nothing, mempty)--  noValueECE sample_vCE es = Just (noValueECE (fromJust sample_vCE) es)--  prependErrorsECE sample_vCE es (Just vCE) =-    Just $ prependErrorsECE (fromJust sample_vCE) es vCE-  prependErrorsECE _sample_vCE _es Nothing = Nothing--instance-  (SuitableForCE es, CanEnsureCE es a)-  =>-  CanEnsureCE es (b -> a)-  where-  type EnsureCE es (b -> a) = b -> (EnsureCE es a)-  type EnsureNoCE es (b -> a) = b ->  (EnsureNoCE es a)--  ensureCE sample_es = ((ensureCE sample_es) .)-  deEnsureCE sample_es f =-    Right $ \ a ->-      case deEnsureCE sample_es (f a) of-        Right v -> v-        Left es -> error $ "deEnsureCE for function: " ++ show es-  ensureNoCE sample_es f = (Just f', mempty)-    where-    f' a =-      case ensureNoCE sample_es (f a) of-        (Just v, _) -> v-        (_, es) -> error $ "ensureNoCE for function: " ++ show es--  noValueECE (_fvCE :: Maybe (b -> a)) es =-    const (noValueECE (Nothing :: Maybe a) es)--  prependErrorsECE (_fvCE :: Maybe (b -> a)) es =-    ((prependErrorsECE (Nothing :: Maybe a) es) .)---- instance (Monoid es) => CanEnsureCE es [a] where--- instance (Monoid es) => CanEnsureCE es (Either e a) where--{-| An unsafe way to get a value out of an CollectErrors wrapper. -}-getValueOrThrowErrorsNCE ::-  (SuitableForCE es, CanEnsureCE es v, Show v)-  =>-  Maybe es {-^ sample only -} ->-  v -> (EnsureNoCE es v)-getValueOrThrowErrorsNCE sample_es v =-  case ensureNoCE sample_es v of-    (Just vNCE, es) | not (hasCertainError es) -> vNCE-    _ -> error (show v)--{-|-  Add error collection support to an unary function whose-  result may already have collected errors.--}-lift1CE ::-  (SuitableForCE es-  , CanEnsureCE es a, CanEnsureCE es c)-  =>-  (a -> c) ->-  (CollectErrors es a) -> (EnsureCE es c)-lift1CE fn aCE =-  case ma of-    Just a ->-      prependErrorsECE sample_c a_es $ ensureCE sample_es $ fn a-    _ ->-      noValueECE sample_c a_es-  where-  CollectErrors ma a_es = aCE-  sample_es = Just a_es-  sample_c = fn <$> ma--{-|-  Add error collection support to a binary function whose-  result may already have collected errors.--}-lift2CE ::-  (SuitableForCE es-  , CanEnsureCE es a, CanEnsureCE es b, CanEnsureCE es c)-  =>-  (a -> b -> c) ->-  (CollectErrors es a) -> (CollectErrors es b) -> (EnsureCE es c)-lift2CE fn aCE bCE =-  case (ma, mb) of-    (Just a, Just b) ->-      prependErrorsECE sample_c ab_es $ ensureCE sample_es $ fn a b-    _ ->-      noValueECE sample_c ab_es-  where-  CollectErrors ma a_es = aCE-  CollectErrors mb b_es = bCE-  ab_es = a_es <> b_es-  sample_es = Just a_es-  sample_c = fn <$> ma <*> mb--{-|-  Add error collection support to a binary function whose-  result may already have collected errors.-  A version where the second operand is not lifted, only the first one.--}-lift2TCE ::-  (SuitableForCE es-  , CanEnsureCE es a, CanEnsureCE es c)-  =>-  (a -> b -> c) ->-  (CollectErrors es a) -> b -> (EnsureCE es c)-lift2TCE fn aCE b =-  case ma of-    (Just a) ->-      prependErrorsECE sample_c a_es $ ensureCE sample_es $ fn a b-    _ ->-      noValueECE sample_c a_es-  where-  CollectErrors ma a_es = aCE-  sample_es = Just a_es-  sample_c = fn <$> ma <*> (Just b)--{-|-  Add error collection support to a binary function whose-  result may already have collected errors.-  A version where the first operand is not lifted, only the second one.--}-lift2TLCE ::-  (SuitableForCE es-  , CanEnsureCE es b, CanEnsureCE es c)-  =>-  (a -> b -> c) ->-  a -> (CollectErrors es b) -> (EnsureCE es c)-lift2TLCE f = flip $ lift2TCE (flip f)--{-|-  Add error collection support to a binary function whose-  result may already have collected errors.--}-lift3CE ::-  (SuitableForCE es-  , CanEnsureCE es a, CanEnsureCE es b, CanEnsureCE es c, CanEnsureCE es d)-  =>-  (a -> b -> c -> d) ->-  (CollectErrors es a) -> (CollectErrors es b) -> (CollectErrors es c) -> (EnsureCE es d)-lift3CE fn aCE bCE cCE =-  case (ma, mb, mc) of-    (Just a, Just b, Just c) ->-      prependErrorsECE sample_d abc_es $ ensureCE sample_es $ fn a b c-    _ ->-      noValueECE sample_d abc_es-  where-  CollectErrors ma a_es = aCE-  CollectErrors mb b_es = bCE-  CollectErrors mc c_es = cCE-  abc_es = a_es <> b_es <> c_es-  sample_es = Just a_es-  sample_d = fn <$> ma <*> mb <*> mc---{-|-  Ability to lift collected (potential) errors from inside some structure/collection.--  This is useful mostly for structures that use the default implementation of-  'CanEnsureCE es'.--}-class (SuitableForCE es) => CanExtractCE es f where-  extractCE ::-    (CanEnsureCE es c) =>-    Maybe es ->-    f c -> CollectErrors es (f (EnsureNoCE es c))-  default extractCE ::-    (CanEnsureCE es c, Traversable f) =>-    Maybe es ->-    f c -> CollectErrors es (f (EnsureNoCE es c))-  extractCE sample_es fc =-    case mapM fst fcNoCE of-      Just fec -> pure fec-      _ -> noValueCE $ foldMap snd fcNoCE-    where-    fcNoCE = fmap (ensureNoCE sample_es) fc
src/Data/Convertible/Base.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -Wno-deprecations #-} {-  Borrowed from package convertible-1.1.1.0.   
src/Data/Convertible/Instances/Num.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -Wno-orphans #-} {-  Borrowed from package convertible-1.1.1.0.   
src/MixedTypesNumPrelude.hs view
@@ -43,16 +43,20 @@   -- * Modules with Prelude alternatives   module Numeric.MixedTypes.Literals,   module Numeric.MixedTypes.Bool,+  module Numeric.MixedTypes.Kleenean,   module Numeric.MixedTypes.Eq,   module Numeric.MixedTypes.Ord,   module Numeric.MixedTypes.MinMaxAbs,   module Numeric.MixedTypes.AddSub,   module Numeric.MixedTypes.Round,+  module Numeric.MixedTypes.Reduce,   module Numeric.MixedTypes.Ring,+  module Numeric.MixedTypes.Div,+  module Numeric.MixedTypes.Power,   module Numeric.MixedTypes.Field,   module Numeric.MixedTypes.Elementary,   module Numeric.MixedTypes.Complex,-  module Numeric.CollectErrors,+  -- module Numeric.CollectErrors,   module Utils.TH.DeclForTypes,   module Utils.Test.EnforceRange,   -- * Re-export for convenient Rational literals@@ -65,16 +69,19 @@ import Data.Convertible.Base import Utils.TH.DeclForTypes import Utils.Test.EnforceRange-import Numeric.CollectErrors import Numeric.MixedTypes.PreludeHiding import Numeric.MixedTypes.Literals import Numeric.MixedTypes.Bool+import Numeric.MixedTypes.Kleenean import Numeric.MixedTypes.Eq import Numeric.MixedTypes.Ord import Numeric.MixedTypes.MinMaxAbs import Numeric.MixedTypes.AddSub import Numeric.MixedTypes.Round+import Numeric.MixedTypes.Reduce import Numeric.MixedTypes.Ring+import Numeric.MixedTypes.Div+import Numeric.MixedTypes.Power import Numeric.MixedTypes.Field import Numeric.MixedTypes.Elementary import Numeric.MixedTypes.Complex@@ -108,71 +115,44 @@ === Dividing integers, dealing with potential error  >...> :t let n = 1 in n/(n+1)->... :: CollectErrors [(ErrorCertaintyLevel, NumError)] Rational+>... :: Rational -A shorter synonym of this type is @CN Rational@.-We use the shorter form below for better readability of this documentation-although ghci usually prints the longer version:+To avoid runtime exceptions, it is recommended to use the CN error-collecting wrapper from package collect-errors: ->...> :t let n = 1 in n/(n+1)+>...> :t let n = cn 1 in n/(n+1) >... :: CN Rational -The @CN@ wrapper here indicates that integer division can fail for some values:+@CN@ is a synonym for @CollectErrors [(ErrorCertaintyLevel, NumError)] Rational@ as defined in module "Numeric.CollectErrors".+The @CN@ wrapper indicates that integer division can fail for some values: ->...> 1/0->{[(ERROR,division by 0)]}+>...> let n = cn 1 in n/(n-1)+>{[(division by 0,ERROR)]} -Note that when evaluating @1/0@, it evaluates to the error value printed above.-This is not an exception, but a special value.+Note that the error printed above is not an exception, but a special value.  All arithmetic operations have been extended to CN types so that it is possible to have expressions that operate exclusively on CN types:  >...> f (n :: CN Integer) = 1/(1/(n-1) + 1/n) :: CN Rational >...> f (cn 0)->{[(ERROR,division by 0)]}+>{[(division by 0,POTENTIAL ERROR),(division by 0,ERROR)]} >...> f (cn 1)->{[(ERROR,division by 0)]}+>{[(division by 0,POTENTIAL ERROR),(division by 0,ERROR)]} >...> f (cn 2) >2 % 3 -The function hasErrorCN can be used to check whether any error occurred:+The function @hasError@ can be used to check whether any error occurred: ->...> hasErrorCN (1/0)+>...> hasError (cn 1/0) >True ->...> hasErrorCN (1/1)+>...> hasError (cn 1/1) >False -When one is certain the division is well defined, one can remove @CN@ as follows:-->...> :t (1/!2)->... :: Rational--Note that if one gets it wrong, it can lead to an exception:-->...> :t (1/!0)->*** Exception: Ratio has zero denominator--More generally, one can remove @CN@ as follows:-->...> :t (~!) (1/2)->... :: Rational--The operator @(/!)@ stands for division which throws an exception is the-denominator is 0.  It "propagates" any potential errors-from the sub-expressions.  For example:-->...> :t 1/!(1 - 1/n)->... :: CN Rational--The above expression will throw an error exception when evaluated with @n=1@-but when @n=0@, it will not throw an excetion but return an error value.--The @(~!)@ operator removes CN from any type, throwing an exception if some errors have certainly occurred:+To extract a value from the CN wrapper, one can use function @withErrorOrValue@: ->...> :t (~!) (1/(1 - 1/n))->... :: Rational+>...> withErrorOrValue (const 0.0) id (cn 1/2)+>1 % 2  The following examples require also package <https://github.com/michalkonecny/aern2 aern2-real>. To get access to this via stack, you can start ghci eg as follows:
− src/Numeric/CollectErrors.hs
@@ -1,155 +0,0 @@-{-|-    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-, hasError, hasErrorCN-, 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, ($), null, not)--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--instance CanTestErrorsPresent NumErrors where-  hasError = not . null--hasErrorCN :: CN v -> Bool-hasErrorCN = hasErrorCE--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
src/Numeric/MixedTypes/AddSub.hs view
@@ -1,3 +1,5 @@+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE TemplateHaskell #-} {-|     Module      :  Numeric.MixedType.AddSub@@ -37,8 +39,8 @@ import Test.Hspec import Test.QuickCheck --- import Numeric.CollectErrors-import Control.CollectErrors+import Control.CollectErrors ( CollectErrors, CanBeErrors )+import qualified Control.CollectErrors as CE  import Numeric.MixedTypes.Literals import Numeric.MixedTypes.Bool@@ -83,30 +85,7 @@   HSpec properties that each implementation of CanAdd should satisfy.  -} specCanAdd ::-  (Show t1, Show t2, Show t3, Show (AddType t1 t1),-   Show (AddType t1 t2), Show (AddType t2 t1),-   Show (AddType t1 (AddType t2 t3)),-   Show (AddType (AddType t1 t2) t3), Arbitrary t1, Arbitrary t2,-   Arbitrary t3, ConvertibleExactly Integer t1,-   CanTestCertainly-     (EqCompareType (AddType t1 t1) t1),-   CanTestCertainly-     (EqCompareType (AddType t1 t2) (AddType t2 t1)),-   CanTestCertainly-     (EqCompareType-        (AddType t1 (AddType t2 t3)) (AddType (AddType t1 t2) t3)),-   CanTestCertainly-     (OrderCompareType (AddType t1 t2) t2),-   HasEqAsymmetric (AddType t1 t1) t1,-   HasEqAsymmetric (AddType t1 t2) (AddType t2 t1),-   HasEqAsymmetric-     (AddType t1 (AddType t2 t3)) (AddType (AddType t1 t2) t3),-   HasOrderAsymmetric (AddType t1 t2) t2, CanTestPosNeg t1,-   CanAddAsymmetric t1 t1, CanAddAsymmetric t1 t2,-   CanAddAsymmetric t1 (AddType t2 t3), CanAddAsymmetric t2 t1,-   CanAddAsymmetric t2 t3, CanAddAsymmetric (AddType t1 t2) t3)-  =>-  T t1 -> T t2 -> T t3 -> Spec+  _ => T t1 -> T t2 -> T t3 -> Spec specCanAdd (T typeName1 :: T t1) (T typeName2 :: T t2) (T typeName3 :: T t3) =   describe (printf "CanAdd %s %s, CanAdd %s %s" typeName1 typeName2 typeName2 typeName3) $ do     it "absorbs 0" $ do@@ -135,24 +114,7 @@   HSpec properties that each implementation of CanAdd should satisfy.  -} specCanAddNotMixed ::-  (Show t, Show (AddType t t), Show (AddType t (AddType t t)),-   Show (AddType (AddType t t) t), Arbitrary t,-   ConvertibleExactly Integer t,-   CanTestCertainly (EqCompareType (AddType t t) t),-   CanTestCertainly (EqCompareType (AddType t t) (AddType t t)),-   CanTestCertainly-     (EqCompareType-        (AddType t (AddType t t)) (AddType (AddType t t) t)),-   CanTestCertainly (OrderCompareType (AddType t t) t),-   HasEqAsymmetric (AddType t t) t,-   HasEqAsymmetric (AddType t t) (AddType t t),-   HasEqAsymmetric-     (AddType t (AddType t t)) (AddType (AddType t t) t),-   HasOrderAsymmetric (AddType t t) t, CanTestPosNeg t,-   CanAddAsymmetric t t, CanAddAsymmetric t (AddType t t),-   CanAddAsymmetric (AddType t t) t)-  =>-  T t -> Spec+  _ => T t -> Spec specCanAddNotMixed (t :: T t) = specCanAdd t t t  {-|@@ -235,16 +197,13 @@   add _ _ = Nothing  instance-  (CanAddAsymmetric a b-  , CanEnsureCE es a, CanEnsureCE es b-  , CanEnsureCE es (AddType a b)-  , SuitableForCE es)+  (CanAddAsymmetric a b, CanBeErrors es)   =>   CanAddAsymmetric (CollectErrors es a) (CollectErrors es  b)   where   type AddType (CollectErrors es a) (CollectErrors es b) =-    EnsureCE es (AddType a b)-  add = lift2CE add+    CollectErrors es (AddType a b)+  add = CE.lift2 add  -- TH for ground type instances at is the end of the file due to a bug in TH @@ -277,17 +236,7 @@   HSpec properties that each implementation of CanSub should satisfy.  -} specCanSub ::-  (Show t1, Show t2, Show (SubType t1 t1), Show (SubType t1 t2),-   Show (AddType t1 (NegType t2)), Arbitrary t1, Arbitrary t2,-   ConvertibleExactly Integer t1,-   CanTestCertainly (EqCompareType (SubType t1 t1) t1),-   CanTestCertainly-     (EqCompareType (SubType t1 t2) (AddType t1 (NegType t2))),-   CanNeg t2, HasEqAsymmetric (SubType t1 t1) t1,-   HasEqAsymmetric (SubType t1 t2) (AddType t1 (NegType t2)),-   CanSub t1 t1, CanSub t1 t2, CanAddAsymmetric t1 (NegType t2))-  =>-  T t1 -> T t2 -> Spec+  _ => T t1 -> T t2 -> Spec specCanSub (T typeName1 :: T t1) (T typeName2 :: T t2) =   describe (printf "CanSub %s %s" typeName1 typeName2) $ do     it "x-0 = x" $ do@@ -306,16 +255,7 @@   HSpec properties that each implementation of CanSub should satisfy.  -} specCanSubNotMixed ::-  (Show t, Show (SubType t t), Show (AddType t (NegType t)),-   Arbitrary t, ConvertibleExactly Integer t,-   CanTestCertainly (EqCompareType (SubType t t) t),-   CanTestCertainly-     (EqCompareType (SubType t t) (AddType t (NegType t))),-   CanNeg t, HasEqAsymmetric (SubType t t) t,-   HasEqAsymmetric (SubType t t) (AddType t (NegType t)), CanSub t t,-   CanAddAsymmetric t (NegType t))-  =>-  T t -> Spec+  _ => T t -> Spec specCanSubNotMixed (t :: T t) = specCanSub t t  instance CanSub Int Int where@@ -380,66 +320,51 @@   instance-  (CanSub a b-  , CanEnsureCE es a, CanEnsureCE es b-  , CanEnsureCE es (SubType a b)-  , SuitableForCE es)+  (CanSub a b, CanBeErrors es)   =>   CanSub (CollectErrors es a) (CollectErrors es  b)   where   type SubType (CollectErrors es a) (CollectErrors es b) =-    EnsureCE es (SubType a b)-  sub = lift2CE sub+    CollectErrors es (SubType a b)+  sub = CE.lift2 sub  $(declForTypes   [[t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]   (\ t -> [d|      instance-      (CanSub $t b-      , CanEnsureCE es b-      , CanEnsureCE es (SubType $t b)-      , SuitableForCE es)+      (CanSub $t b, CanBeErrors es)       =>       CanSub $t (CollectErrors es  b)       where       type SubType $t (CollectErrors es  b) =-        EnsureCE es (SubType $t b)-      sub = lift2TLCE sub+        CollectErrors es (SubType $t b)+      sub = CE.liftT1 sub      instance-      (CanSub a $t-      , CanEnsureCE es a-      , CanEnsureCE es (SubType a $t)-      , SuitableForCE es)+      (CanSub a $t, CanBeErrors es)       =>       CanSub (CollectErrors es a) $t       where       type SubType (CollectErrors es  a) $t =-        EnsureCE es (SubType a $t)-      sub = lift2TCE sub+        CollectErrors es (SubType a $t)+      sub = CE.lift1T sub      instance-      (CanAddAsymmetric $t b-      , CanEnsureCE es b-      , CanEnsureCE es (AddType $t b)-      , SuitableForCE es)+      (CanAddAsymmetric $t b, CanBeErrors es)       =>       CanAddAsymmetric $t (CollectErrors es  b)       where       type AddType $t (CollectErrors es  b) =-        EnsureCE es (AddType $t b)-      add = lift2TLCE add+        CollectErrors es (AddType $t b)+      add = CE.liftT1 add      instance-      (CanAddAsymmetric a $t-      , CanEnsureCE es a-      , CanEnsureCE es (AddType a $t)-      , SuitableForCE es)+      (CanAddAsymmetric a $t, CanBeErrors es)       =>       CanAddAsymmetric (CollectErrors es a) $t       where       type AddType (CollectErrors es  a) $t =-        EnsureCE es (AddType a $t)-      add = lift2TCE add+        CollectErrors es (AddType a $t)+      add = CE.lift1T add   |]))
src/Numeric/MixedTypes/Bool.hs view
@@ -1,3 +1,6 @@+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# OPTIONS_GHC -Wno-orphans #-} {-|     Module      :  Numeric.MixedType.Bool     Description :  Bottom-up typed Boolean operations@@ -9,7 +12,6 @@     Portability :  portable  -}- module Numeric.MixedTypes.Bool (   IsBool, specIsBool@@ -35,8 +37,8 @@  import qualified Data.List as List --- import Numeric.CollectErrors-import Control.CollectErrors+import Control.CollectErrors ( CollectErrors, CanBeErrors )+import qualified Control.CollectErrors as CE  import Numeric.MixedTypes.Literals @@ -109,23 +111,11 @@   isCertainlyTrue = id   isCertainlyFalse = not -instance (ConvertibleExactly Bool t) => ConvertibleExactly Bool (Maybe t) where-  safeConvertExactly b =-    case (safeConvertExactly b) of-      Left _ -> Right Nothing-      Right r -> Right (Just r)--instance (CanTestCertainly t) => CanTestCertainly (Maybe t) where-  isCertainlyTrue (Just b) = isCertainlyTrue b-  isCertainlyTrue _ = False-  isCertainlyFalse (Just b) = isCertainlyFalse b-  isCertainlyFalse _ = False--instance (CanTestCertainly t, SuitableForCE es) => CanTestCertainly (CollectErrors es t) where+instance (CanTestCertainly t, CanBeErrors es) => CanTestCertainly (CollectErrors es t) where   isCertainlyTrue vCE =-    getValueIfNoErrorCE vCE isCertainlyTrue (const False)+    CE.withErrorOrValue (const False) isCertainlyTrue vCE   isCertainlyFalse vCE =-    getValueIfNoErrorCE vCE isCertainlyFalse (const False)+    CE.withErrorOrValue (const False) isCertainlyFalse vCE   {---- Negation ----}@@ -157,12 +147,7 @@   HSpec properties that each Boolean implementation of CanNeg should satisfy.  -} specCanNegBool ::-  (Show t, Show (NegType (NegType t)), SCS.Serial IO t,-   CanTestCertainly t, CanTestCertainly (NegType t),-   CanTestCertainly (NegType (NegType t)), CanNeg t,-   CanNeg (NegType t))-  =>-  T t -> Spec+  _ => T t -> Spec specCanNegBool (T typeName :: T t) =   describe (printf "CanNeg %s" typeName) $ do     it "ignores double negation" $ do@@ -177,19 +162,12 @@  instance CanNeg Bool where negate = P.not -instance CanNeg t => CanNeg (Maybe t) where-  type NegType (Maybe t) = Maybe (NegType t)-  negate = fmap negate--_testNeg1 :: Maybe Bool-_testNeg1 = not (Just True)- instance-  (CanNeg t, SuitableForCE es, CanEnsureCE es t, CanEnsureCE es (NegType t))+  (CanNeg t, CanBeErrors es)   =>   CanNeg (CollectErrors es t) where-  type NegType (CollectErrors es t) = EnsureCE es (NegType t)-  negate = lift1CE negate+  type NegType (CollectErrors es t) = CollectErrors es (NegType t)+  negate = fmap negate  {---- And/Or ----} @@ -232,31 +210,7 @@ {-|   HSpec properties that each implementation of CanAndOr should satisfy.  -}-specCanAndOr ::-  (Show t1, Show t2, Show t3, Show (AndOrType t1 t1),-   Show (AndOrType t1 t2), Show (AndOrType t2 t1),-   Show (AndOrType t1 (AndOrType t2 t3)),-   Show (AndOrType (AndOrType t1 t2) t3),-   Show (AndOrType (AndOrType t1 t2) (AndOrType t1 t3)),-   Show (NegType (AndOrType t1 t2)),-   Show (AndOrType (NegType t1) (NegType t2)), SCS.Serial IO t1,-   SCS.Serial IO t2, SCS.Serial IO t3, CanTestCertainly t1,-   CanTestCertainly (AndOrType t1 t1),-   CanTestCertainly (AndOrType t1 t2),-   CanTestCertainly (AndOrType t2 t1),-   CanTestCertainly (AndOrType t1 (AndOrType t2 t3)),-   CanTestCertainly (AndOrType (AndOrType t1 t2) t3),-   CanTestCertainly (AndOrType (AndOrType t1 t2) (AndOrType t1 t3)),-   CanTestCertainly (NegType (AndOrType t1 t2)),-   CanTestCertainly (AndOrType (NegType t1) (NegType t2)), CanNeg t1,-   CanNeg t2, CanNeg (AndOrType t1 t2), CanAndOrAsymmetric t1 t1,-   CanAndOrAsymmetric t1 t2, CanAndOrAsymmetric t1 t3,-   CanAndOrAsymmetric t1 (AndOrType t2 t3), CanAndOrAsymmetric t2 t1,-   CanAndOrAsymmetric t2 t3, CanAndOrAsymmetric (AndOrType t1 t2) t3,-   CanAndOrAsymmetric (AndOrType t1 t2) (AndOrType t1 t3),-   CanAndOrAsymmetric (NegType t1) (NegType t2))-  =>-  T t1 -> T t2 -> T t3 -> Spec+specCanAndOr :: _ => T t1 -> T t2 -> T t3 -> Spec specCanAndOr (T typeName1 ::T t1) (T typeName2 :: T t2) (T typeName3 :: T t3) =   describe (printf "CanAndOr %s %s, CanAndOr %s %s" typeName1 typeName2 typeName2 typeName3) $ do     it "has idempotent ||" $ do@@ -287,26 +241,7 @@ {-|   HSpec properties that each implementation of CanAndOr should satisfy.  -}-specCanAndOrNotMixed ::-  (Show t, Show (AndOrType t t),-   Show (AndOrType t (AndOrType t t)),-   Show (AndOrType (AndOrType t t) t),-   Show (AndOrType (AndOrType t t) (AndOrType t t)),-   Show (NegType (AndOrType t t)),-   Show (AndOrType (NegType t) (NegType t)), SCS.Serial IO t,-   CanTestCertainly t, CanTestCertainly (AndOrType t t),-   CanTestCertainly (AndOrType t (AndOrType t t)),-   CanTestCertainly (AndOrType (AndOrType t t) t),-   CanTestCertainly (AndOrType (AndOrType t t) (AndOrType t t)),-   CanTestCertainly (NegType (AndOrType t t)),-   CanTestCertainly (AndOrType (NegType t) (NegType t)), CanNeg t,-   CanNeg (AndOrType t t), CanAndOrAsymmetric t t,-   CanAndOrAsymmetric t (AndOrType t t),-   CanAndOrAsymmetric (AndOrType t t) t,-   CanAndOrAsymmetric (AndOrType t t) (AndOrType t t),-   CanAndOrAsymmetric (NegType t) (NegType t))-  =>-  T t -> Spec+specCanAndOrNotMixed :: _ => T t -> Spec specCanAndOrNotMixed t = specCanAndOr t t t  instance CanAndOrAsymmetric Bool Bool where@@ -314,90 +249,39 @@   and2 = (P.&&)   or2 = (P.||) -instance (CanAndOrAsymmetric t1 t2, CanTestCertainly t1, CanTestCertainly t2, CanTestCertainly (AndOrType t1 t2)) =>-  CanAndOrAsymmetric (Maybe t1) (Maybe t2)-  where-  type AndOrType (Maybe t1) (Maybe t2) = Maybe (AndOrType t1 t2)-  and2 (Just b1) _ | isCertainlyFalse b1 = Just (convertExactly False)-  and2 _ (Just b2) | isCertainlyFalse b2 = Just (convertExactly False)-  and2 (Just b1) (Just b2) = Just (b1 && b2)-  and2 _ _ = Nothing-  or2 (Just b1) _ | isCertainlyTrue b1 = Just (convertExactly True)-  or2 _ (Just b2) | isCertainlyTrue b2 = Just (convertExactly True)-  or2 (Just b1) (Just b2) = Just (b1 || b2)-  or2 _ _ = Nothing--instance (CanAndOrAsymmetric Bool t2, CanTestCertainly t2, CanTestCertainly (AndOrType Bool t2)) =>-  CanAndOrAsymmetric Bool (Maybe t2)-  where-  type AndOrType Bool (Maybe t2) = Maybe (AndOrType Bool t2)-  and2 False _ = Just (convertExactly False)-  and2 _ (Just b2) | isCertainlyFalse b2 = Just (convertExactly False)-  and2 b1 (Just b2) = Just (b1 && b2)-  and2 _ _ = Nothing-  or2 True _ = Just (convertExactly True)-  or2 _ (Just b2) | isCertainlyTrue b2 = Just (convertExactly True)-  or2 b1 (Just b2) = Just (b1 || b2)-  or2 _ _ = Nothing--instance (CanAndOrAsymmetric t1 Bool, CanTestCertainly t1, CanTestCertainly (AndOrType t1 Bool)) =>-  CanAndOrAsymmetric (Maybe t1) Bool-  where-  type AndOrType (Maybe t1) Bool = Maybe (AndOrType t1 Bool)-  and2 _ False = Just (convertExactly False)-  and2 (Just b1) _ | isCertainlyFalse b1 = Just (convertExactly False)-  and2 (Just b1) b2 = Just (b1 && b2)-  and2 _ _ = Nothing-  or2 _ True = Just (convertExactly True)-  or2 (Just b1) _ | isCertainlyTrue b1 = Just (convertExactly True)-  or2 (Just b1) b2 = Just (b1 || b2)-  or2 _ _ = Nothing--_testAndOr1 :: Maybe Bool-_testAndOr1 = (Just True) && False--_testAndOr2 :: Maybe (Maybe Bool)-_testAndOr2 = (Just (Just True)) || False--_testAndOr3 :: Maybe Bool-_testAndOr3 = and [Just True, Nothing, Just False]- instance-  (CanAndOrAsymmetric t1 t2, SuitableForCE es-  , CanEnsureCE es t1, CanEnsureCE es t2, CanEnsureCE es (AndOrType t1 t2))+  (CanAndOrAsymmetric t1 t2, CanBeErrors es)   =>   CanAndOrAsymmetric (CollectErrors es t1) (CollectErrors es t2)   where-  type AndOrType (CollectErrors es t1) (CollectErrors es t2) = EnsureCE es (AndOrType t1 t2)-  and2 = lift2CE and2-  or2 = lift2CE or2+  type AndOrType (CollectErrors es t1) (CollectErrors es t2) = CollectErrors es (AndOrType t1 t2)+  and2 = CE.lift2 and2+  or2 = CE.lift2 or2  instance-  (CanAndOrAsymmetric t1 Bool, SuitableForCE es-  , CanEnsureCE es t1, CanEnsureCE es (AndOrType t1 Bool))+  (CanAndOrAsymmetric t1 Bool, CanBeErrors es)   =>   CanAndOrAsymmetric (CollectErrors es t1) Bool   where-  type AndOrType (CollectErrors es t1) Bool = EnsureCE es (AndOrType t1 Bool)-  and2 = lift2TCE and2-  or2 = lift2TCE or2+  type AndOrType (CollectErrors es t1) Bool = CollectErrors es (AndOrType t1 Bool)+  and2 = CE.lift1T and2+  or2 = CE.lift1T or2  instance-  (CanAndOrAsymmetric Bool t2, SuitableForCE es-  , CanEnsureCE es t2, CanEnsureCE es (AndOrType Bool t2))+  (CanAndOrAsymmetric Bool t2, CanBeErrors es)   =>   CanAndOrAsymmetric Bool (CollectErrors es t2)   where-  type AndOrType Bool (CollectErrors es t2) = EnsureCE es (AndOrType Bool t2)-  and2 = lift2TLCE and2-  or2 = lift2TLCE or2+  type AndOrType Bool (CollectErrors es t2) = CollectErrors es (AndOrType Bool t2)+  and2 = CE.liftT1 and2+  or2 = CE.liftT1 or2  {-|   A type constraint synonym that stipulates that the type behaves very   much like Bool, except it does not necessarily satisfy the law of excluded middle,-  which means that the type can contain a "do-not-know" value.+  which means that the type can contain a "do-not-know" value or an error. -  Examples: @Bool@, @Maybe Bool@, @Maybe (Maybe Bool)@, @CollectErrors Bool@+  Examples: @Bool@, @Kleenean@, @CollectErrors Bool@ -} type IsBool t =   (HasBools t, CanNegSameType t, CanAndOrSameType t)
src/Numeric/MixedTypes/Complex.hs view
@@ -12,6 +12,7 @@     Instances for "Data.Complex". -} +{-# OPTIONS_GHC -Wno-orphans #-} module Numeric.MixedTypes.Complex (   tComplex@@ -32,7 +33,9 @@ import Numeric.MixedTypes.MinMaxAbs import Numeric.MixedTypes.AddSub import Numeric.MixedTypes.Ring-import Numeric.MixedTypes.Field+import Numeric.MixedTypes.Div+-- import Numeric.MixedTypes.Power+-- import Numeric.MixedTypes.Field import Numeric.MixedTypes.Elementary  tComplex :: T t -> T (Complex t)@@ -116,10 +119,6 @@   divide (a1 :+ i1) (a2 :+ i2) =     let d = a2*a2 + i2*i2 in     ((a1*a2 + i1*i2)/d) :+ ((i1*a2-a1*i2)/d)-  type DivTypeNoCN (Complex a) (Complex b) = Complex (DivTypeNoCN (MulType a b) (MulType b b))-  divideNoCN (a1 :+ i1) (a2 :+ i2) =-    let d = a2*a2 + i2*i2 in-    ((a1*a2 + i1*i2)/!d) :+ ((i1*a2-a1*i2)/!d)  instance   (CanMulAsymmetric t t@@ -194,16 +193,10 @@       divide n (a2 :+ i2) =         let d = a2*a2 + i2*i2 in         ((n*a2)/d) :+ (((-n)*i2)/d)-      type DivTypeNoCN $t (Complex b) = Complex (DivTypeNoCN (MulType $t b) (MulType b b))-      divideNoCN n (a2 :+ i2) =-        let d = a2*a2 + i2*i2 in-        ((n*a2)/!d) :+ (((-n)*i2)/!d)      instance       (CanDiv a $t) => CanDiv (Complex a) $t       where       type DivType (Complex a) $t = Complex (DivType a $t)       divide (a1 :+ i1) n = (a1/n) :+ (i1/n)-      type DivTypeNoCN (Complex a) $t = Complex (DivTypeNoCN a $t)-      divideNoCN (a1 :+ i1) n = (a1/!n) :+ (i1/!n)   |]))
+ src/Numeric/MixedTypes/Div.hs view
@@ -0,0 +1,208 @@+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE TemplateHaskell #-}+{-|+    Module      :  Numeric.MixedType.Div+    Description :  Bottom-up typed division+    Copyright   :  (c) Michal Konecny+    License     :  BSD3++    Maintainer  :  mikkonecny@gmail.com+    Stability   :  experimental+    Portability :  portable++-}++module Numeric.MixedTypes.Div+(+  -- * Division+    CanDiv(..), CanDivBy, CanDivSameType+  , CanRecip, CanRecipSameType+  , (/), recip+  -- ** Tests+  , specCanDiv, specCanDivNotMixed+)+where++import Utils.TH.DeclForTypes++import Numeric.MixedTypes.PreludeHiding+import qualified Prelude as P+import Text.Printf++-- import qualified Data.List as List++import Test.Hspec+import Test.QuickCheck++import Numeric.CollectErrors ( CN, cn )+import qualified Numeric.CollectErrors as CN++import Numeric.MixedTypes.Literals+import Numeric.MixedTypes.Bool+import Numeric.MixedTypes.Eq+-- import Numeric.MixedTypes.Ord+-- import Numeric.MixedTypes.MinMaxAbs+-- import Numeric.MixedTypes.AddSub+import Numeric.MixedTypes.Ring++{---- Division -----}++{-|+  A replacement for Prelude's binary `P./`.  If @t1 = t2@ and @Fractional t1@,+  then one can use the default implementation to mirror Prelude's @/@.+-}+class CanDiv t1 t2 where+  type DivType t1 t2+  type DivType t1 t2 = t1+  divide :: t1 -> t2 -> DivType t1 t2++divideCN ::+  (CanTestZero t2)+  =>+  (t1 -> t2 -> t3) ->+  CN t1 -> CN t2 -> CN t3+divideCN unsafeDivide a b+  | isCertainlyZero b = CN.noValueNumErrorCertain e+  | isCertainlyNonZero b = r+  | otherwise = CN.noValueNumErrorPotential e+  where+  r = CN.lift2 unsafeDivide a b+  e :: CN.NumError+  e = CN.DivByZero++infixl 7  /++(/) :: (CanDiv t1 t2) => t1 -> t2 -> DivType t1 t2+(/) = divide++type CanRecip t =+  (CanDiv Integer t)++type CanRecipSameType t =+  (CanDiv Integer t, DivType Integer t ~ t)++recip :: (CanRecip t) => t -> DivType Integer t+recip = divide 1++type CanDivBy t1 t2 =+  (CanDiv t1 t2, DivType t1 t2 ~ t1)+type CanDivSameType t =+  CanDivBy t t++{-|+  HSpec properties that each implementation of CanDiv should satisfy.+ -}+specCanDiv ::+  _ => T t1 -> T t2 -> Spec+specCanDiv (T typeName1 :: T t1) (T typeName2 :: T t2) =+  describe (printf "CanDiv %s %s" typeName1 typeName2) $ do+    it "recip(recip x) = x" $ do+      property $ \ (x :: t1) ->+        (isCertainlyNonZero x && isCertainlyNonZero (recip x)) ==>+          recip (recip x) ?==?$ x+    it "x/1 = x" $ do+      property $ \ (x :: t1) -> let one = (convertExactly 1 :: t2) in (x / one) ?==?$ x+    it "x/x = 1" $ do+      property $ \ (x :: t1) ->+        (isCertainlyNonZero x) ==>+          let one = (convertExactly 1 :: t1) in (x / x) ?==?$ one+    it "x/y = x*(1/y)" $ do+      property $ \ (x :: t1) (y :: t2) ->+        (isCertainlyNonZero y) ==>+          let one = (convertExactly 1 :: t1) in (x / y) ?==?$ x * (one/y)+  where+  infix 4 ?==?$+  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property+  (?==?$) = printArgsIfFails2 "?==?" (?==?)++{-|+  HSpec properties that each implementation of CanDiv should satisfy.+ -}+specCanDivNotMixed ::+  _ => T t -> Spec+specCanDivNotMixed (t :: T t) = specCanDiv t t++instance CanDiv Int Int where+  type DivType Int Int = Rational+  divide a b = (P./) (rational a) (rational b)++instance CanDiv Integer Integer where+  type DivType Integer Integer = Rational+  divide a b = (P./) (rational a) (rational b)+instance CanDiv Rational Rational where+  type DivType Rational Rational = Rational+  divide = (P./)++instance CanDiv Int Integer where+  type DivType Int Integer = Rational+  divide a b = (P./) (rational a) (rational b)+instance CanDiv Integer Int where+  type DivType Integer Int = Rational+  divide a b = (P./) (rational a) (rational b)++instance CanDiv Int Rational where+  type DivType Int Rational = Rational+  divide = convertFirst divide+instance CanDiv Rational Int where+  divide = convertSecond divide++instance CanDiv Integer Rational where+  type DivType Integer Rational = Rational+  divide = convertFirst divide+instance CanDiv Rational Integer where+  divide = convertSecond divide++instance CanDiv Double Double where+  divide = (P./)++$(declForTypes+  [[t| Integer |], [t| Int |], [t| Rational |]]+  (\ t -> [d|++    instance CanDiv $t Double where+      type DivType $t Double = Double+      divide n d = divide (double n) d+    instance CanDiv Double $t where+      type DivType Double $t = Double+      divide d n = divide d (double n)+  |]))++instance (CanDiv a b) => CanDiv [a] [b] where+  type DivType [a] [b] = [DivType a b]+  divide (x:xs) (y:ys) = (divide x y) : (divide xs ys)+  divide _ _ = []++instance (CanDiv a b) => CanDiv (Maybe a) (Maybe b) where+  type DivType (Maybe a) (Maybe b) = Maybe (DivType a b)+  divide (Just x) (Just y) = Just (divide x y)+  divide _ _ = Nothing++instance+  (CanDiv a b, CanTestZero b)+  =>+  CanDiv (CN a) (CN  b)+  where+  type DivType (CN a) (CN b) = CN (DivType a b)+  divide  = divideCN divide++$(declForTypes+  [[t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]+  (\ t -> [d|++    instance+      (CanDiv $t b, CanTestZero b)+      =>+      CanDiv $t (CN  b)+      where+      type DivType $t (CN b) = CN (DivType $t b)+      divide a b = divideCN divide (cn a) b++    instance+      (CanDiv a $t)+      =>+      CanDiv (CN a) $t+      where+      type DivType (CN a) $t = CN (DivType a $t)+      divide a b = divideCN divide a (cn b)+  |]))
src/Numeric/MixedTypes/Elementary.hs view
@@ -1,3 +1,5 @@+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# LANGUAGE PartialTypeSignatures #-} {-|     Module      :  Numeric.MixedType.Elementary     Description :  Bottom-up typed pi, sqrt, cos, etc@@ -9,15 +11,14 @@     Portability :  portable  -}- module Numeric.MixedTypes.Elementary (   -- * Square root-  CanSqrt(..), CanSqrtSameType, CanSqrtCNSameType, specCanSqrtReal+  CanSqrt(..), CanSqrtSameType, specCanSqrtReal   -- * Exp   , CanExp(..), CanExpSameType, specCanExpReal   -- * Log-  , CanLog(..), CanLogSameType, CanLogCNSameType, specCanLogReal+  , CanLog(..), CanLogSameType, specCanLogReal   , powUsingExpLog   -- * Sine and cosine   , CanSinCos(..), CanSinCosSameType, specCanSinCosReal@@ -34,17 +35,18 @@ import Test.Hspec import Test.QuickCheck -import Numeric.CollectErrors-import Control.CollectErrors+import Numeric.CollectErrors ( CN )+import qualified Numeric.CollectErrors as CN  import Numeric.MixedTypes.Literals import Numeric.MixedTypes.Bool import Numeric.MixedTypes.Eq import Numeric.MixedTypes.Ord--- import Numeric.MixedTypes.MinMaxAbs+import Numeric.MixedTypes.MinMaxAbs import Numeric.MixedTypes.AddSub import Numeric.MixedTypes.Ring import Numeric.MixedTypes.Field+import Numeric.MixedTypes.Power -- import Numeric.MixedTypes.Round  import Utils.Test.EnforceRange @@ -63,21 +65,12 @@   sqrt = P.sqrt  type CanSqrtSameType t = (CanSqrt t, SqrtType t ~ t)-type CanSqrtCNSameType t = (CanSqrt t, SqrtType t ~ EnsureCN t)  {-|   HSpec properties that each implementation of CanSqrt should satisfy.  -} specCanSqrtReal ::-  (Show t, Show (SqrtType t), Show (PowType (SqrtType t) Integer),-    Arbitrary t,-    CanTestCertainly (OrderCompareType (SqrtType t) Integer),-    CanTestCertainly (EqCompareType (PowType (SqrtType t) Integer) t),-    HasEqAsymmetric (PowType (SqrtType t) Integer) t,-    HasOrderAsymmetric (SqrtType t) Integer, CanTestPosNeg t,-    CanPow (SqrtType t) Integer, CanSqrt t)-  =>-  T t -> Spec+  _ => T t -> Spec specCanSqrtReal (T typeName :: T t) =   describe (printf "CanSqrt %s" typeName) $ do     it "sqrt(x) >= 0" $ do@@ -104,15 +97,18 @@ instance CanSqrt Double -- not exact, will not pass the tests  instance-  (CanSqrt a-  , CanEnsureCE es a-  , CanEnsureCE es (SqrtType a)-  , SuitableForCE es)+  (CanSqrt a, CanTestPosNeg a, CanMinMaxThis a Integer)   =>-  CanSqrt (CollectErrors es a)+  CanSqrt (CN a)   where-  type SqrtType (CollectErrors es a) = EnsureCE es (SqrtType a)-  sqrt = lift1CE sqrt+  type SqrtType (CN a) = CN (SqrtType a)+  sqrt x +    | isCertainlyNonNegative x = CN.lift sqrt x+    | isCertainlyNegative x = CN.noValueNumErrorCertain err+    | otherwise = CN.prependErrorPotential err $ CN.lift sqrt $ max x 0+    where+    err :: CN.NumError+    err = CN.OutOfDomain "negative sqrt argument"   {----  exp -----}@@ -134,33 +130,7 @@   HSpec properties that each implementation of CanExp should satisfy.  -} specCanExpReal ::-  (Show t, Show (ExpType t), Show (DivType Integer (ExpType t)),-   Show (ExpType (AddType t t)),-   Show (MulType (ExpType t) (ExpType t)),-   Show (EnsureCN (ExpType t)), Arbitrary t,-   CanEnsureCN (ExpType t),-   CanTestCertainly (OrderCompareType Integer t),-   CanTestCertainly (OrderCompareType t Integer),-   CanTestCertainly (OrderCompareType (ExpType t) Integer),-   CanTestCertainly-     (EqCompareType-        (EnsureCN (ExpType t)) (DivType Integer (ExpType t))),-   CanTestCertainly-     (EqCompareType-        (ExpType (AddType t t)) (MulType (ExpType t) (ExpType t))),-   CanNeg t,-   HasEqAsymmetric-     (ExpType (AddType t t)) (MulType (ExpType t) (ExpType t)),-   HasEqAsymmetric-     (EnsureCN (ExpType t)) (DivType Integer (ExpType t)),-   HasOrderAsymmetric t Integer,-   HasOrderAsymmetric (ExpType t) Integer,-   HasOrderAsymmetric Integer t, CanAddAsymmetric t t,-   CanMulAsymmetric (ExpType t) (ExpType t),-   CanDiv Integer (ExpType t), CanExp t, CanExp (AddType t t),-   NegType t ~ t, -   CanEnforceRange t Integer) =>-   T t -> Spec+  _ => T t -> Spec specCanExpReal (T typeName :: T t) =   describe (printf "CanExp %s" typeName) $ do     it "exp(x) >= 0" $ do@@ -172,7 +142,7 @@         let x = enforceRange (Just (-100000), Just 100000) x_ in         let ex = exp x in           (ex !>! 0) ==>-            (ensureCN $ exp (-x)) ?==?$ 1/ex+            (exp (-x)) ?==?$ 1/ex     it "exp(x+y) = exp(x)*exp(y)" $ do       property $ \ (x_ :: t)  (y_ :: t) ->         let x = enforceRange (Just (-100000), Just 100000) x_ in@@ -194,15 +164,10 @@ instance CanExp Double -- not exact, will not pass the tests  instance-  (CanExp a-  , CanEnsureCE es a-  , CanEnsureCE es (ExpType a)-  , SuitableForCE es)-  =>-  CanExp (CollectErrors es a)+  (CanExp a) => CanExp (CN a)   where-  type ExpType (CollectErrors es a) = EnsureCE es (ExpType a)-  exp = lift1CE exp+  type ExpType (CN a) = CN (ExpType a)+  exp = CN.lift exp  {----  log -----} @@ -218,42 +183,12 @@   log = P.log  type CanLogSameType t = (CanLog t, LogType t ~ t)-type CanLogCNSameType t = (CanLog t, LogType t ~ EnsureCN t)  {-|   HSpec properties that each implementation of CanLog should satisfy.  -} specCanLogReal ::-  (Show t, Show (LogType t), Show (LogType (DivType Integer t)),-   Show (LogType (MulType t t)),-   Show (AddType (LogType t) (LogType t)), Show (LogType (ExpType t)),-   Arbitrary t, CanTestCertainly (OrderCompareType t Integer),-   CanTestCertainly (OrderCompareType (DivType Integer t) Integer),-   CanTestCertainly-     (EqCompareType (LogType (DivType Integer t)) (LogType t)),-   CanTestCertainly (OrderCompareType (MulType t t) Integer),-   CanTestCertainly (OrderCompareType (ExpType t) Integer),-   CanTestCertainly-     (EqCompareType-        (LogType (MulType t t)) (AddType (LogType t) (LogType t))),-   CanTestCertainly (OrderCompareType Integer t),-   CanTestCertainly (EqCompareType (LogType (ExpType t)) t),-   CanNeg (LogType t),-   HasEqAsymmetric (LogType (DivType Integer t)) (LogType t),-   HasEqAsymmetric-     (LogType (MulType t t)) (AddType (LogType t) (LogType t)),-   HasEqAsymmetric (LogType (ExpType t)) t,-   HasOrderAsymmetric t Integer,-   HasOrderAsymmetric (DivType Integer t) Integer,-   HasOrderAsymmetric (MulType t t) Integer,-   HasOrderAsymmetric (ExpType t) Integer,-   HasOrderAsymmetric Integer t,-   CanAddAsymmetric (LogType t) (LogType t), CanMulAsymmetric t t,-   CanDiv Integer t, CanExp t, CanLog t, CanLog (DivType Integer t),-   CanLog (MulType t t), CanLog (ExpType t),-   LogType t ~ NegType (LogType t),-   CanEnforceRange t Integer) =>-  T t -> Spec+  _ => T t -> Spec specCanLogReal (T typeName :: T t) =   describe (printf "CanLog %s" typeName) $ do     it "log(1/x) == -(log x)" $ do@@ -286,65 +221,36 @@ instance CanLog Double -- not exact, will not pass the tests  instance-  (CanLog a-  , CanEnsureCE es a-  , CanEnsureCE es (LogType a)-  , SuitableForCE es)+  (CanLog a, CanTestPosNeg a)   =>-  CanLog (CollectErrors es a)+  CanLog (CN a)   where-  type LogType (CollectErrors es a) = EnsureCE es (LogType a)-  log = lift1CE log+  type LogType (CN a) = CN (LogType a)+  log x +    | isCertainlyPositive x = logx+    | isCertainlyNonPositive x = CN.noValueNumErrorCertain err+    | otherwise = CN.noValueNumErrorPotential err+    where+    logx = CN.lift log x+    err :: CN.NumError+    err = CN.OutOfDomain "log argument not positive" -instance CanPow Double Double where-  powNoCN = (P.**)-  type PowType Double Double = Double-  pow = (P.**)-instance CanPow Double Rational where-  powNoCN b e = b ^! (double e)-  type PowType Double Rational = Double-  pow b e = b ^ (double e)-instance CanPow Rational Double where-  type PowTypeNoCN Rational Double = Double-  powNoCN b e = (double b) ^! e-  type PowType Rational Double = Double-  pow b e = (double b) ^ e-instance CanPow Integer Double where-  type PowTypeNoCN Integer Double = Double-  powNoCN b e = (double b) ^! e-  type PowType Integer Double = Double-  pow b e = (double b) ^ e-instance CanPow Int Double where-  type PowTypeNoCN Int Double = Double-  powNoCN b e = (double b) ^! e-  type PowType Int Double = Double-  pow b e = (double b) ^ e  powUsingExpLog ::-  (CanTestPosNeg t,-   CanEnsureCN t,-   CanEnsureCN (EnsureCN t),-   EnsureCN t ~ EnsureCN (EnsureCN t),-   CanLogCNSameType t,+  (CanLogSameType t,+   CanExpSameType t,    CanMulSameType t,-   CanMulSameType (EnsureCN t),-   CanExpSameType (EnsureCN t),    CanTestInteger t,    CanTestZero t,-   CanRecipCNSameType t)+   CanRecipSameType t)   =>-  t -> t -> t -> t -> EnsureCN t-powUsingExpLog zero one b e =+  t -> t -> t -> t+powUsingExpLog one b e =   case certainlyIntegerGetIt e of     Just n ->       powUsingMulRecip one b n-    Nothing-      | isCertainlyZero b && isCertainlyPositive e -> cn zero-      | isCertainlyNonNegative b -> exp ((log b) * (ensureCN e))-      | isCertainlyNegative b && certainlyNotInteger e -> noValueNumErrorCertainECN (Just b) err-      | otherwise -> noValueNumErrorPotentialECN (Just b) err-  where-  err = NumError "powUsingExpLog: illegal power a^b with negative a and non-integer b"+    Nothing ->+      exp ((log b) * (e))  {----  sine and cosine -----} @@ -371,81 +277,7 @@   http://math.stackexchange.com/questions/1303044/axiomatic-definition-of-sin-and-cos  -} specCanSinCosReal ::- (Show t, Show (SinCosType t),-  Show-    (AddType-       (PowType (SinCosType t) Integer) (PowType (SinCosType t) Integer)),-  Show (SinCosType (SubType t t)),-  Show-    (SubType-       (MulType (SinCosType t) (SinCosType t))-       (MulType (SinCosType t) (SinCosType t))),-  Show-    (AddType-       (MulType (SinCosType t) (SinCosType t))-       (MulType (SinCosType t) (SinCosType t))),-  Show (DivType (SinCosType t) (SinCosType t)),-  Show (EnsureCN t), Arbitrary t, CanEnsureCN t,-  CanTestCertainly (OrderCompareType Integer (SinCosType t)),-  CanTestCertainly (OrderCompareType (SinCosType t) Integer),-  CanTestCertainly-    (EqCompareType-       (AddType-          (PowType (SinCosType t) Integer)-          (PowType (SinCosType t) Integer))-       Integer),-  CanTestCertainly-    (EqCompareType-       (SinCosType (SubType t t))-       (SubType-          (MulType (SinCosType t) (SinCosType t))-          (MulType (SinCosType t) (SinCosType t)))),-  CanTestCertainly-    (EqCompareType-       (SinCosType (SubType t t))-       (AddType-          (MulType (SinCosType t) (SinCosType t))-          (MulType (SinCosType t) (SinCosType t)))),-  CanTestCertainly (OrderCompareType t Integer),-  CanTestCertainly (OrderCompareType t Rational),-  CanTestCertainly (OrderCompareType (SinCosType t) t),-  CanTestCertainly-    (OrderCompareType-       (EnsureCN t) (DivType (SinCosType t) (SinCosType t))),-  HasEqAsymmetric-    (AddType-       (PowType (SinCosType t) Integer) (PowType (SinCosType t) Integer))-    Integer,-  HasEqAsymmetric-    (SinCosType (SubType t t))-    (SubType-       (MulType (SinCosType t) (SinCosType t))-       (MulType (SinCosType t) (SinCosType t))),-  HasEqAsymmetric-    (SinCosType (SubType t t))-    (AddType-       (MulType (SinCosType t) (SinCosType t))-       (MulType (SinCosType t) (SinCosType t))),-  HasOrderAsymmetric t Integer, HasOrderAsymmetric t Rational,-  HasOrderAsymmetric (SinCosType t) t,-  HasOrderAsymmetric (SinCosType t) Integer,-  HasOrderAsymmetric-    (EnsureCN t) (DivType (SinCosType t) (SinCosType t)),-  HasOrderAsymmetric Integer (SinCosType t), CanSub t t,-  CanSub-    (MulType (SinCosType t) (SinCosType t))-    (MulType (SinCosType t) (SinCosType t)),-  CanAddAsymmetric-    (PowType (SinCosType t) Integer) (PowType (SinCosType t) Integer),-  CanAddAsymmetric-    (MulType (SinCosType t) (SinCosType t))-    (MulType (SinCosType t) (SinCosType t)),-  CanPow (SinCosType t) Integer,-  CanMulAsymmetric (SinCosType t) (SinCosType t),-  CanDiv (SinCosType t) (SinCosType t), CanSinCos t,-  CanSinCos (SubType t t))-  =>-  T t -> Spec+  _ => T t -> Spec specCanSinCosReal (T typeName :: T t) =   describe (printf "CanSinCos %s" typeName) $ do     it "-1 <= sin(x) <= 1" $ do@@ -466,7 +298,7 @@     it "sin(x) < x < tan(x) for x in [0,pi/2]" $ do       property $ \ (x :: t) ->         x !>=! 0 && x !<=! 1.57 && (cos x) !>! 0 ==>-          (sin x) ?<=?$ x .&&. (ensureCN x) ?<=?$ (sin x)/(cos x)+          (sin x) ?<=?$ x .&&. (x) ?<=?$ (sin x)/(cos x)   where   infix 4 ?==?$   (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property@@ -483,16 +315,11 @@ instance CanSinCos Double -- not exact, will not pass the tests  instance-  (CanSinCos a-  , CanEnsureCE es a-  , CanEnsureCE es (SinCosType a)-  , SuitableForCE es)-  =>-  CanSinCos (CollectErrors es a)+  (CanSinCos a) => CanSinCos (CN a)   where-  type SinCosType (CollectErrors es a) = EnsureCE es (SinCosType a)-  sin = lift1CE sin-  cos = lift1CE cos+  type SinCosType (CN a) = CN (SinCosType a)+  sin = CN.lift sin+  cos = CN.lift cos  {-|   Approximate pi, synonym for Prelude's `P.pi`.
src/Numeric/MixedTypes/Eq.hs view
@@ -1,3 +1,5 @@+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE TemplateHaskell #-} {-|     Module      :  Numeric.MixedType.Eq@@ -15,7 +17,6 @@   -- * Equality checks   HasEq,  HasEqAsymmetric(..), (==), (/=)   , HasEqCertainly, HasEqCertainlyAsymmetric-  , HasEqCertainlyCE, HasEqCertainlyCN   , notCertainlyDifferentFrom, certainlyEqualTo, certainlyNotEqualTo   , (?==?), (!==!), (!/=!)   -- ** Tests@@ -40,8 +41,8 @@ import Test.Hspec import Test.QuickCheck as QC -import Numeric.CollectErrors-import Control.CollectErrors+import Control.CollectErrors ( CollectErrors, CanBeErrors )+import qualified Control.CollectErrors as CE  import Numeric.MixedTypes.Literals import Numeric.MixedTypes.Bool@@ -62,19 +63,6 @@ type HasEqCertainly t1 t2 =   (HasEq t1 t2, CanTestCertainly (EqCompareType t1 t2)) -type HasEqCertainlyCE es t1 t2 =-  (HasEqCertainly t1 t2,-   HasEqCertainly (EnsureCE es t1) (EnsureCE es t2))-  --  HasEqCertainly (WithoutCE es t1) (WithoutCE es t2),-  --  CanTestCertainly (WithoutCE es (EqCompareType (WithoutCE es t1) (WithoutCE es t2))),-  --  IsBool (WithoutCE es (EqCompareType (WithoutCE es t1) (WithoutCE es t2))),-  --  CanEnsureCE es (EqCompareType (WithoutCE es t1) (WithoutCE es t2)),-  --  CanEnsureCE es (WithoutCE es (EqCompareType (WithoutCE es t1) (WithoutCE es t2))),-  --  WithoutCE es (WithoutCE es (EqCompareType (WithoutCE es t1) (WithoutCE es t2)))-  --    ~ (WithoutCE es (EqCompareType (WithoutCE es t1) (WithoutCE es t2))))--type HasEqCertainlyCN t1 t2 = HasEqCertainlyCE NumErrors t1 t2- class (IsBool (EqCompareType a b)) => HasEqAsymmetric a b where     type EqCompareType a b     type EqCompareType a b = Bool -- default@@ -113,19 +101,8 @@ {-|   HSpec properties that each implementation of HasEq should satisfy.  -}-specHasEq ::- (Show t1, Show t2, Show t3, Arbitrary t1, Arbitrary t2,-  Arbitrary t3, CanTestCertainly (EqCompareType t1 t1),-  CanTestCertainly (EqCompareType t1 t2),-  CanTestCertainly (EqCompareType t2 t1),-  CanTestCertainly (EqCompareType t2 t3),-  CanTestCertainly-    (AndOrType (EqCompareType t1 t2) (EqCompareType t2 t3)),-  CanAndOrAsymmetric (EqCompareType t1 t2) (EqCompareType t2 t3),-  HasEqAsymmetric t1 t1, HasEqAsymmetric t1 t2,-  HasEqAsymmetric t2 t1, HasEqAsymmetric t2 t3)-  =>-  T t1 -> T t2 -> T t3 -> Spec+specHasEq :: +  _ => T t1 -> T t2 -> T t3 -> Spec specHasEq (T typeName1 :: T t1) (T typeName2 :: T t2) (T typeName3 :: T t3) =   describe (printf "HasEq %s %s, HasEq %s %s" typeName1 typeName2 typeName2 typeName3) $ do     it "has reflexive ==" $ do@@ -143,12 +120,7 @@   HSpec properties that each implementation of HasEq should satisfy.  -} specHasEqNotMixed ::-  (Show t, Arbitrary t, CanTestCertainly (EqCompareType t t),-   CanTestCertainly-     (AndOrType (EqCompareType t t) (EqCompareType t t)),-   HasEqAsymmetric t t)-  =>-  T t -> Spec+  _ => T t -> Spec specHasEqNotMixed (t :: T t) = specHasEq t t t  {-|@@ -249,47 +221,35 @@   equalTo _ _ = convertExactly False  instance-  (HasEqAsymmetric a b-  , CanEnsureCE es (EqCompareType a b)-  , CanEnsureCE es a, CanEnsureCE es b-  , IsBool (EnsureCE es (EqCompareType a b))-  , SuitableForCE es)+  (HasEqAsymmetric a b, CanBeErrors es)   =>   HasEqAsymmetric (CollectErrors es a) (CollectErrors es  b)   where   type EqCompareType (CollectErrors es  a) (CollectErrors es  b) =-    EnsureCE es (EqCompareType a b)-  equalTo = lift2CE equalTo+    CollectErrors es (EqCompareType a b)+  equalTo = CE.lift2 equalTo  $(declForTypes   [[t| Bool |], [t| Maybe Bool |], [t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]   (\ t -> [d|      instance-      (HasEqAsymmetric $t b-      , CanEnsureCE es b-      , CanEnsureCE es (EqCompareType $t b)-      , IsBool (EnsureCE es (EqCompareType $t b))-      , SuitableForCE es)+      (HasEqAsymmetric $t b, CanBeErrors es)       =>       HasEqAsymmetric $t (CollectErrors es  b)       where       type EqCompareType $t (CollectErrors es  b) =-        EnsureCE es (EqCompareType $t b)-      equalTo = lift2TLCE equalTo+        CollectErrors es (EqCompareType $t b)+      equalTo = CE.liftT1 equalTo      instance-      (HasEqAsymmetric a $t-      , CanEnsureCE es a-      , CanEnsureCE es (EqCompareType a $t)-      , IsBool (EnsureCE es (EqCompareType a $t))-      , SuitableForCE es)+      (HasEqAsymmetric a $t, CanBeErrors es)       =>       HasEqAsymmetric (CollectErrors es a) $t       where       type EqCompareType (CollectErrors es  a) $t =-        EnsureCE es (EqCompareType a $t)-      equalTo = lift2TCE equalTo+        CollectErrors es (EqCompareType a $t)+      equalTo = CE.lift1T equalTo    |])) @@ -326,12 +286,12 @@   isInfinite = const False   isFinite = const True -instance (CanTestNaN t, SuitableForCE es) => (CanTestNaN (CollectErrors es t)) where-  isNaN ce = getValueIfNoErrorCE ce isNaN (const False)+instance (CanTestNaN t, CanBeErrors es) => (CanTestNaN (CollectErrors es t)) where+  isNaN = CE.withErrorOrValue (const False) isNaN -instance (CanTestFinite t, SuitableForCE es) => (CanTestFinite (CollectErrors es t)) where-  isInfinite ce = getValueIfNoErrorCE ce isInfinite (const False)-  isFinite ce = getValueIfNoErrorCE ce isFinite (const False)+instance (CanTestFinite t, CanBeErrors es) => (CanTestFinite (CollectErrors es t)) where+  isInfinite = CE.withErrorOrValue (const False) isInfinite+  isFinite = CE.withErrorOrValue (const False) isFinite  {---- Checking whether it is an integer -----} @@ -369,9 +329,9 @@       dF = P.floor d       dC = P.ceiling d -instance (CanTestInteger t, SuitableForCE es) => (CanTestInteger (CollectErrors es t)) where-  certainlyNotInteger ce = getValueIfNoErrorCE ce certainlyNotInteger (const False)-  certainlyIntegerGetIt ce = getValueIfNoErrorCE ce certainlyIntegerGetIt (const Nothing)+instance (CanTestInteger t, CanBeErrors es) => (CanTestInteger (CollectErrors es t)) where+  certainlyNotInteger = CE.withErrorOrValue (const False) certainlyNotInteger+  certainlyIntegerGetIt = CE.withErrorOrValue (const Nothing) certainlyIntegerGetIt  {---- Checking whether it is zero -----} @@ -406,9 +366,9 @@ instance CanTestZero Rational instance CanTestZero Double -instance (CanTestZero t, SuitableForCE es) => (CanTestZero (CollectErrors es t)) where-  isCertainlyZero ce = getValueIfNoErrorCE ce isCertainlyZero (const False)-  isCertainlyNonZero ce = getValueIfNoErrorCE ce isCertainlyNonZero (const False)+instance (CanTestZero t, CanBeErrors es) => (CanTestZero (CollectErrors es t)) where+  isCertainlyZero = CE.withErrorOrValue (const False) isCertainlyZero+  isCertainlyNonZero = CE.withErrorOrValue (const False) isCertainlyNonZero   class CanPickNonZero t where@@ -457,9 +417,9 @@ instance CanPickNonZero Integer instance CanPickNonZero Rational -instance (CanPickNonZero a, SuitableForCE es) => (CanPickNonZero (CollectErrors es a)) where+instance (CanPickNonZero a, CanBeErrors es) => (CanPickNonZero (CollectErrors es a)) where   pickNonZero =     fmap (\(v,s) -> (pure v,s))     . pickNonZero-    . filterValuesWithoutErrorCE+    . CE.filterValuesWithoutError     . (map (\(vCN,s) -> fmap (\v -> (v,s)) vCN))
src/Numeric/MixedTypes/Field.hs view
@@ -14,50 +14,40 @@ module Numeric.MixedTypes.Field (   -- * Field-  CanAddSubMulDivCNBy, Field, OrderedField, OrderedCertainlyField+  CanAddSubMulDivBy, Field, OrderedField, OrderedCertainlyField   -- * Division-  , CanDiv(..), CanDivBy, CanDivCNBy, CanDivSameType, CanDivCNSameType-  , CanRecip, CanRecipSameType, CanRecipCNSameType-  , (/), (/!), recip-  , powUsingMulRecip-  -- ** Tests-  , specCanDiv, specCanDivNotMixed+  , module Numeric.MixedTypes.Div ) where -import Utils.TH.DeclForTypes- import Numeric.MixedTypes.PreludeHiding-import qualified Prelude as P-import Text.Printf---- import qualified Data.List as List--import Test.Hspec-import Test.QuickCheck+-- import qualified Prelude as P -import Numeric.CollectErrors-import Control.CollectErrors+import Numeric.CollectErrors ( CN )+-- import qualified Numeric.CollectErrors as CN -import Numeric.MixedTypes.Literals-import Numeric.MixedTypes.Bool-import Numeric.MixedTypes.Eq+-- import Numeric.MixedTypes.Literals+-- import Numeric.MixedTypes.Bool+-- import Numeric.MixedTypes.Eq import Numeric.MixedTypes.Ord -- import Numeric.MixedTypes.MinMaxAbs -- import Numeric.MixedTypes.AddSub import Numeric.MixedTypes.Ring+import Numeric.MixedTypes.Div+import Numeric.MixedTypes.Power  {----- Field -----} -type CanAddSubMulDivCNBy t s =-  (CanAddSubMulBy t s, CanAddSubMulBy (EnsureCN t) s, CanDivCNBy t s)+type CanAddSubMulDivBy t s =+  (CanAddSubMulBy t s, CanAddSubMulBy t s, CanDivBy t s)  class   (Ring t,-   CanDivCNSameType t, CanRecipCNSameType t,-   CanAddSubMulDivCNBy t Rational,-   CanAddSubMulDivCNBy t Integer,-   CanAddSubMulDivCNBy t Int+   CanPowBy t Integer, CanPowBy t Int,+   CanDivSameType t, CanRecipSameType t,+   CanAddSubMulDivBy t Rational,+   CanAddSubMulDivBy t Integer,+   CanAddSubMulDivBy t Int   )   =>   Field t@@ -66,281 +56,15 @@ instance Field (CN Rational)  class-  (Field t, OrderedRing t, HasOrder t Rational, HasOrder (EnsureCN t) Rational)+  (Field t, OrderedRing t, HasOrder t Rational, HasOrder t Rational)   => OrderedField t  instance OrderedField Rational instance OrderedField (CN Rational)  class-  (Field t, OrderedCertainlyRing t, HasOrderCertainly t Rational, HasOrderCertainly (EnsureCN t) Rational)+  (Field t, OrderedCertainlyRing t, HasOrderCertainly t Rational, HasOrderCertainly t Rational)   => OrderedCertainlyField t  instance OrderedCertainlyField Rational instance OrderedCertainlyField (CN Rational)--{---- Division -----}--{-|-  A replacement for Prelude's binary `P./`.  If @t1 = t2@ and @Fractional t1@,-  then one can use the default implementation to mirror Prelude's @/@.--}-class CanDiv t1 t2 where-  type DivTypeNoCN t1 t2-  divideNoCN :: t1 -> t2 -> DivTypeNoCN t1 t2-  type DivType t1 t2-  type DivType t1 t2 = EnsureCN (DivTypeNoCN t1 t2)-  divide :: t1 -> t2 -> DivType t1 t2-  default divide ::-    (CanTestZero t2, CanEnsureCN (DivTypeNoCN t1 t2)-    , DivType t1 t2 ~ EnsureCN (DivTypeNoCN t1 t2))-    =>-    t1 -> t2 -> DivType t1 t2-  divide = divideCN divideNoCN--divideCN ::-  (CanTestZero t2, CanEnsureCN t3)-  =>-  (t1 -> t2 -> t3) ->-  t1 -> t2 -> EnsureCN t3-divideCN unsafeDivide a b-  | isCertainlyZero b = noValueNumErrorCertainECN sample_v DivByZero-  | isCertainlyNonZero b = ensureCN $ a `unsafeDivide` b-  | otherwise = noValueNumErrorPotentialECN sample_v DivByZero-  where-  sample_v = Just $ unsafeDivide a b--infixl 7  /,/!--(/) :: (CanDiv t1 t2) => t1 -> t2 -> DivType t1 t2-(/) = divide--(/!) :: (CanDiv t1 t2) => t1 -> t2 -> DivTypeNoCN t1 t2-(/!) = divideNoCN--type CanRecip t =-  (CanDiv Integer t)--type CanRecipSameType t =-  (CanDiv Integer t, DivType Integer t ~ t, DivTypeNoCN Integer t ~ t)--type CanRecipCNSameType t =-  (CanDiv Integer t, DivType Integer t ~ EnsureCN t, DivTypeNoCN Integer t ~ t-  ,CanEnsureCN t-  ,CanDiv Integer (EnsureCN t), DivType Integer (EnsureCN t) ~ EnsureCN t, DivTypeNoCN Integer (EnsureCN t) ~ (EnsureCN t))--recip :: (CanRecip t) => t -> DivType Integer t-recip = divide 1--type CanDivBy t1 t2 =-  (CanDiv t1 t2, DivType t1 t2 ~ t1, DivTypeNoCN t1 t2 ~ t1)-type CanDivSameType t =-  CanDivBy t t--type CanDivCNBy t1 t2 =-  (CanDiv t1 t2, DivType t1 t2 ~ EnsureCN t1, DivTypeNoCN t1 t2 ~ t1-  , CanEnsureCN t1-  , CanDiv (EnsureCN t1) t2, DivType (EnsureCN t1) t2 ~ EnsureCN t1, DivTypeNoCN (EnsureCN t1) t2 ~ (EnsureCN t1))-type CanDivCNSameType t =-  (CanDivCNBy t t-  , CanDiv (EnsureCN t) (EnsureCN t), DivType (EnsureCN t) (EnsureCN t) ~ EnsureCN t, DivTypeNoCN (EnsureCN t) (EnsureCN t) ~ (EnsureCN t))--{-|-  HSpec properties that each implementation of CanDiv should satisfy.- -}-specCanDiv ::-  (Show t1, Show t2, Show (DivType Integer (DivType Integer t1)),-   Show (DivType t1 t2), Show (DivType t1 t1),-   Show (MulType t1 (DivType t1 t2)), Arbitrary t1, Arbitrary t2,-   ConvertibleExactly Integer t1, ConvertibleExactly Integer t2,-   CanTestCertainly-     (EqCompareType (DivType Integer (DivType Integer t1)) t1),-   CanTestCertainly (EqCompareType (DivType t1 t2) t1),-   CanTestCertainly (EqCompareType (DivType t1 t1) t1),-   CanTestCertainly-     (EqCompareType (DivType t1 t2) (MulType t1 (DivType t1 t2))),-   HasEqAsymmetric (DivType Integer (DivType Integer t1)) t1,-   HasEqAsymmetric (DivType t1 t2) t1,-   HasEqAsymmetric (DivType t1 t2) (MulType t1 (DivType t1 t2)),-   HasEqAsymmetric (DivType t1 t1) t1, CanTestZero t1, CanTestZero t2,-   CanTestZero (DivType Integer t1),-   CanMulAsymmetric t1 (DivType t1 t2), CanDiv t1 t1, CanDiv t1 t2,-   CanDiv Integer t1, CanDiv Integer (DivType Integer t1))-  =>-  T t1 -> T t2 -> Spec-specCanDiv (T typeName1 :: T t1) (T typeName2 :: T t2) =-  describe (printf "CanDiv %s %s" typeName1 typeName2) $ do-    it "recip(recip x) = x" $ do-      property $ \ (x :: t1) ->-        (isCertainlyNonZero x && isCertainlyNonZero (recip x)) ==>-          recip (recip x) ?==?$ x-    it "x/1 = x" $ do-      property $ \ (x :: t1) -> let one = (convertExactly 1 :: t2) in (x / one) ?==?$ x-    it "x/x = 1" $ do-      property $ \ (x :: t1) ->-        (isCertainlyNonZero x) ==>-          let one = (convertExactly 1 :: t1) in (x / x) ?==?$ one-    it "x/y = x*(1/y)" $ do-      property $ \ (x :: t1) (y :: t2) ->-        (isCertainlyNonZero y) ==>-          let one = (convertExactly 1 :: t1) in (x / y) ?==?$ x * (one/y)-  where-  infix 4 ?==?$-  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property-  (?==?$) = printArgsIfFails2 "?==?" (?==?)--{-|-  HSpec properties that each implementation of CanDiv should satisfy.- -}-specCanDivNotMixed ::-  (Show t, Show (DivType Integer (DivType Integer t)),-   Show (DivType t t), Show (MulType t (DivType t t)), Arbitrary t,-   ConvertibleExactly Integer t,-   CanTestCertainly-     (EqCompareType (DivType Integer (DivType Integer t)) t),-   CanTestCertainly (EqCompareType (DivType t t) t),-   CanTestCertainly-     (EqCompareType (DivType t t) (MulType t (DivType t t))),-   HasEqAsymmetric (DivType Integer (DivType Integer t)) t,-   HasEqAsymmetric (DivType t t) t,-   HasEqAsymmetric (DivType t t) (MulType t (DivType t t)),-   CanTestZero t, CanTestZero (DivType Integer t),-   CanMulAsymmetric t (DivType t t), CanDiv t t, CanDiv Integer t,-   CanDiv Integer (DivType Integer t))-  =>-  T t -> Spec-specCanDivNotMixed (t :: T t) = specCanDiv t t--instance CanDiv Int Int where-  type DivTypeNoCN Int Int = Rational-  divideNoCN a b = (P./) (rational a) (rational b)--instance CanDiv Integer Integer where-  type DivTypeNoCN Integer Integer = Rational-  divideNoCN a b = (P./) (rational a) (rational b)-instance CanDiv Rational Rational where-  type DivTypeNoCN Rational Rational = Rational-  divideNoCN = (P./)--instance CanDiv Int Integer where-  type DivTypeNoCN Int Integer = Rational-  divideNoCN a b = (P./) (rational a) (rational b)-instance CanDiv Integer Int where-  type DivTypeNoCN Integer Int = Rational-  divideNoCN a b = (P./) (rational a) (rational b)--instance CanDiv Int Rational where-  type DivTypeNoCN Int Rational = Rational-  divideNoCN = convertFirst divideNoCN-instance CanDiv Rational Int where-  type DivTypeNoCN Rational Int = Rational-  divideNoCN = convertSecond divideNoCN--instance CanDiv Integer Rational where-  type DivTypeNoCN Integer Rational = Rational-  divideNoCN = convertFirst divideNoCN-instance CanDiv Rational Integer where-  type DivTypeNoCN Rational Integer = Rational-  divideNoCN = convertSecond divideNoCN--instance CanDiv Double Double where-  type DivTypeNoCN Double Double = Double-  divideNoCN = (P./)-  type DivType Double Double = Double-  divide = (P./)--$(declForTypes-  [[t| Integer |], [t| Int |], [t| Rational |]]-  (\ t -> [d|--    instance CanDiv $t Double where-      type DivType $t Double = Double-      divide n d = divide (double n) d-      type DivTypeNoCN $t Double = Double-      divideNoCN n d = divide (double n) d-    instance CanDiv Double $t where-      type DivType Double $t = Double-      divide d n = divide d (double n)-      type DivTypeNoCN Double $t = Double-      divideNoCN d n = divide d (double n)-  |]))--instance (CanDiv a b) => CanDiv [a] [b] where-  type DivTypeNoCN [a] [b] = [DivTypeNoCN a b]-  divideNoCN (x:xs) (y:ys) = (divideNoCN x y) : (divideNoCN xs ys)-  divideNoCN _ _ = []-  type DivType [a] [b] = [DivType a b]-  divide (x:xs) (y:ys) = (divide x y) : (divide xs ys)-  divide _ _ = []--instance (CanDiv a b) => CanDiv (Maybe a) (Maybe b) where-  type DivType (Maybe a) (Maybe b) = Maybe (DivType a b)-  divide (Just x) (Just y) = Just (divide x y)-  divide _ _ = Nothing-  type DivTypeNoCN (Maybe a) (Maybe b) = Maybe (DivTypeNoCN a b)-  divideNoCN (Just x) (Just y) = Just (divideNoCN x y)-  divideNoCN _ _ = Nothing--instance-  (CanDiv a b-  , CanEnsureCE es a, CanEnsureCE es b-  , CanEnsureCE es (DivType a b)-  , CanEnsureCE es (DivTypeNoCN a b)-  , SuitableForCE es)-  =>-  CanDiv (CollectErrors es a) (CollectErrors es  b)-  where-  type DivType (CollectErrors es a) (CollectErrors es b) =-    EnsureCE es (DivType a b)-  divide = lift2CE divide-  type DivTypeNoCN (CollectErrors es a) (CollectErrors es b) =-    EnsureCE es (DivTypeNoCN a b)-  divideNoCN = lift2CE divideNoCN--powUsingMulRecip ::-  (CanBeInteger e,-   CanRecipCNSameType t, CanMulSameType t, CanEnsureCN t)-   =>-   t -> t -> e -> EnsureCN t-powUsingMulRecip one x nPre-  | n < 0 = recip $ powUsingMul one x (negate n)-  | otherwise = ensureCN $ powUsingMul one x n-  where-  n = integer nPre--$(declForTypes-  [[t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]-  (\ t -> [d|--    instance-      (CanDiv $t b-      , CanEnsureCE es b-      , CanEnsureCE es (DivType $t b)-      , CanEnsureCE es (DivTypeNoCN $t b)-      , SuitableForCE es)-      =>-      CanDiv $t (CollectErrors es  b)-      where-      type DivType $t (CollectErrors es  b) =-        EnsureCE es (DivType $t b)-      divide = lift2TLCE divide-      type DivTypeNoCN $t (CollectErrors es  b) =-        EnsureCE es (DivTypeNoCN $t b)-      divideNoCN = lift2TLCE divideNoCN--    instance-      (CanDiv a $t-      , CanEnsureCE es a-      , CanEnsureCE es (DivType a $t)-      , CanEnsureCE es (DivTypeNoCN a $t)-      , SuitableForCE es)-      =>-      CanDiv (CollectErrors es a) $t-      where-      type DivType (CollectErrors es  a) $t =-        EnsureCE es (DivType a $t)-      divide = lift2TCE divide-      type DivTypeNoCN (CollectErrors es  a) $t =-        EnsureCE es (DivTypeNoCN a $t)-      divideNoCN = lift2TCE divideNoCN-  |]))
+ src/Numeric/MixedTypes/Kleenean.hs view
@@ -0,0 +1,87 @@+{-# OPTIONS_GHC -Wno-orphans #-}+{-|+    Module      :  Numeric.MixedType.Kleenean+    Description :  Three-valued logic+    Copyright   :  (c) Michal Konecny+    License     :  BSD3++    Maintainer  :  mikkonecny@gmail.com+    Stability   :  experimental+    Portability :  portable++-}+module Numeric.MixedTypes.Kleenean+(+    Kleenean(..), kleenean+)+where++import Numeric.MixedTypes.PreludeHiding+import qualified Prelude as P++import Numeric.MixedTypes.Literals+    ( ConvertibleExactly(..), convertExactly )+import Numeric.MixedTypes.Bool+    ( (&&),+      not,+      CanAndOrAsymmetric(..),+      CanNeg(negate),+      CanTestCertainly(..),+      and )++data Kleenean = CertainTrue | CertainFalse | TrueOrFalse+  deriving (P.Eq, Show)++type CanBeKleenean t = ConvertibleExactly t Kleenean+kleenean :: (CanBeKleenean t) => t -> Kleenean+kleenean = convertExactly++instance ConvertibleExactly Kleenean Kleenean where+  safeConvertExactly = Right++instance ConvertibleExactly Bool Kleenean where+  safeConvertExactly True = Right CertainTrue+  safeConvertExactly False = Right CertainFalse++instance CanTestCertainly Kleenean where+  isCertainlyTrue = (P.== CertainTrue)+  isCertainlyFalse = (P.== CertainFalse)++instance CanNeg Kleenean where+  negate CertainTrue = CertainFalse+  negate CertainFalse = CertainTrue+  negate TrueOrFalse = TrueOrFalse++_testNeg1 :: Kleenean+_testNeg1 = not CertainTrue++instance CanAndOrAsymmetric Kleenean Kleenean+  where+  type AndOrType Kleenean Kleenean = Kleenean+  and2 CertainTrue CertainTrue = CertainTrue+  and2 CertainFalse _ = CertainFalse+  and2 _ CertainFalse = CertainFalse+  and2 _ _ = TrueOrFalse+  or2 CertainFalse CertainFalse = CertainFalse+  or2 CertainTrue _ = CertainTrue+  or2 _ CertainTrue = CertainTrue+  or2 _ _ = TrueOrFalse++instance CanAndOrAsymmetric Bool Kleenean+  where+  type AndOrType Bool Kleenean = Kleenean+  and2 b = and2 (kleenean b)+  or2 b = or2 (kleenean b)++instance CanAndOrAsymmetric Kleenean Bool+  where+  type AndOrType Kleenean Bool = Kleenean+  and2 k b = and2 k (kleenean b)+  or2 k b = or2 k (kleenean b)++_testAndOr1 :: Kleenean+_testAndOr1 = TrueOrFalse && False++_testAndOr2 :: Kleenean+_testAndOr2 = and [CertainTrue, TrueOrFalse, CertainFalse]+
src/Numeric/MixedTypes/Literals.hs view
@@ -49,7 +49,7 @@   -- * Prelude List operations versions without Int   , (!!), length, replicate, take, drop, splitAt   -- * Testing support functions-  , T(..), tInt, tInteger, tRational, tDouble+  , T(..), tInt, tInteger, tCNInteger, tRational, tCNRational, tDouble   , tBool, tMaybe, tMaybeBool, tMaybeMaybeBool   , specCanBeInteger   , printArgsIfFails2@@ -75,7 +75,7 @@ import Test.QuickCheck -- import Control.Exception (evaluate) --- import Numeric.CollectErrors+import Numeric.CollectErrors (CN) import Control.CollectErrors  {-| Replacement for 'Prelude.fromInteger' using the RebindableSyntax extension.@@ -251,9 +251,15 @@ tInteger :: T Integer tInteger = T "Integer" +tCNInteger :: T (CN Integer)+tCNInteger = T "(CN Integer)"+ tRational :: T Rational tRational = T "Rational" +tCNRational :: T (CN Rational)+tCNRational = T "(CN Rational)"+ tDouble :: T Double tDouble = T "Double" @@ -296,7 +302,7 @@ convertSecond = convertSecondUsing (\ _ b -> convertExactly b)  -- instance---   (ConvertibleExactly t1 t2, SuitableForCE es)+--   (ConvertibleExactly t1 t2, CanBeErrors es) --   => --   ConvertibleExactly t1 (CollectErrors es t2) --   where@@ -308,5 +314,5 @@   (\ t -> [d|      instance (ConvertibleExactly $t t, Monoid es) => ConvertibleExactly $t (CollectErrors es t) where-      safeConvertExactly = fmap (\v -> CollectErrors (Just v) mempty) . safeConvertExactly+      safeConvertExactly = fmap pure . safeConvertExactly   |]))
src/Numeric/MixedTypes/MinMaxAbs.hs view
@@ -1,3 +1,6 @@+{-# OPTIONS_GHC -Wno-orphans #-}+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE TemplateHaskell #-} {-|     Module      :  Numeric.MixedType.MinMaxAbs@@ -36,8 +39,8 @@ import Test.Hspec import Test.QuickCheck --- import Numeric.CollectErrors-import Control.CollectErrors+import Control.CollectErrors ( CollectErrors, CanBeErrors )+import qualified Control.CollectErrors as CE  import Numeric.MixedTypes.Literals import Numeric.MixedTypes.Bool@@ -81,38 +84,7 @@   HSpec properties that each implementation of CanMinMax should satisfy.  -} specCanMinMax ::- (Show t1, Show t2, Show t3, Show (MinMaxType t1 t2),-  Show (MinMaxType t1 t1), Show (MinMaxType t2 t1),-  Show (MinMaxType t1 (MinMaxType t2 t3)),-  Show (MinMaxType (MinMaxType t1 t2) t3), Arbitrary t1,-  Arbitrary t2, Arbitrary t3, CanTestCertainly (EqCompareType t1 t1),-  CanTestCertainly (EqCompareType t2 t2),-  CanTestCertainly (OrderCompareType (MinMaxType t1 t2) t2),-  CanTestCertainly (OrderCompareType (MinMaxType t1 t2) t1),-  CanTestCertainly (EqCompareType (MinMaxType t1 t1) t1),-  CanTestCertainly-    (EqCompareType (MinMaxType t1 t2) (MinMaxType t2 t1)),-  CanTestCertainly (EqCompareType t3 t3),-  CanTestCertainly-    (EqCompareType-       (MinMaxType t1 (MinMaxType t2 t3))-       (MinMaxType (MinMaxType t1 t2) t3)),-  CanTestFinite t1, CanTestFinite t2, CanTestFinite t3,-  HasEqAsymmetric t1 t1, HasEqAsymmetric t2 t2,-  HasEqAsymmetric t3 t3,-  HasEqAsymmetric (MinMaxType t1 t2) (MinMaxType t2 t1),-  HasEqAsymmetric (MinMaxType t1 t1) t1,-  HasEqAsymmetric-    (MinMaxType t1 (MinMaxType t2 t3))-    (MinMaxType (MinMaxType t1 t2) t3),-  HasOrderAsymmetric (MinMaxType t1 t2) t1,-  HasOrderAsymmetric (MinMaxType t1 t2) t2,-  CanMinMaxAsymmetric t1 t1, CanMinMaxAsymmetric t1 t2,-  CanMinMaxAsymmetric t1 (MinMaxType t2 t3),-  CanMinMaxAsymmetric t2 t1, CanMinMaxAsymmetric t2 t3,-  CanMinMaxAsymmetric (MinMaxType t1 t2) t3)-  =>-  T t1 -> T t2 -> T t3 -> Spec+  _ => T t1 -> T t2 -> T t3 -> Spec specCanMinMax (T typeName1 :: T t1) (T typeName2 :: T t2) (T typeName3 :: T t3) =   describe (printf "CanMinMax %s %s, CanMinMax %s %s" typeName1 typeName2 typeName2 typeName3) $ do     it "`min` is not larger than its arguments" $ do@@ -167,30 +139,7 @@   HSpec properties that each implementation of CanMinMax should satisfy.  -} specCanMinMaxNotMixed ::- (Show t, Show (MinMaxType t t),-  Show (MinMaxType t (MinMaxType t t)),-  Show (MinMaxType (MinMaxType t t) t), Arbitrary t,-  CanTestCertainly (EqCompareType t t),-  CanTestCertainly (OrderCompareType (MinMaxType t t) t),-  CanTestCertainly (EqCompareType (MinMaxType t t) t),-  CanTestCertainly-    (EqCompareType (MinMaxType t t) (MinMaxType t t)),-  CanTestCertainly-    (EqCompareType-       (MinMaxType t (MinMaxType t t))-       (MinMaxType (MinMaxType t t) t)),-  CanTestFinite t,-  HasEqAsymmetric t t, HasEqAsymmetric (MinMaxType t t) t,-  HasEqAsymmetric (MinMaxType t t) (MinMaxType t t),-  HasEqAsymmetric-    (MinMaxType t (MinMaxType t t))-    (MinMaxType (MinMaxType t t) t),-  HasOrderAsymmetric (MinMaxType t t) t,-  CanMinMaxAsymmetric t t,-  CanMinMaxAsymmetric t (MinMaxType t t),-  CanMinMaxAsymmetric (MinMaxType t t) t)-  =>-  T t -> Spec+  _ => T t -> Spec specCanMinMaxNotMixed t = specCanMinMax t t t  instance CanMinMaxAsymmetric Int Int@@ -240,72 +189,49 @@   max _ _ = Nothing  instance-  (CanMinMaxAsymmetric a b-  , CanEnsureCE es a, CanEnsureCE es b-  , CanEnsureCE es (MinMaxType a b)-  , SuitableForCE es)+  (CanMinMaxAsymmetric a b, CanBeErrors es)   =>   CanMinMaxAsymmetric (CollectErrors es a) (CollectErrors es  b)   where   type MinMaxType (CollectErrors es a) (CollectErrors es b) =-    EnsureCE es (MinMaxType a b)-  min = lift2CE min-  max = lift2CE max+    CollectErrors es (MinMaxType a b)+  min = CE.lift2 min+  max = CE.lift2 max  $(declForTypes   [[t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]   (\ t -> [d|      instance-      (CanMinMaxAsymmetric $t b-      , CanEnsureCE es b-      , CanEnsureCE es (MinMaxType $t b)-      , SuitableForCE es)+      (CanMinMaxAsymmetric $t b, CanBeErrors es)       =>       CanMinMaxAsymmetric $t (CollectErrors es  b)       where       type MinMaxType $t (CollectErrors es  b) =-        EnsureCE es (MinMaxType $t b)-      min = lift2TLCE min-      max = lift2TLCE max+        CollectErrors es (MinMaxType $t b)+      min = CE.liftT1 min+      max = CE.liftT1 max      instance-      (CanMinMaxAsymmetric a $t-      , CanEnsureCE es a-      , CanEnsureCE es (MinMaxType a $t)-      , SuitableForCE es)+      (CanMinMaxAsymmetric a $t, CanBeErrors es)       =>       CanMinMaxAsymmetric (CollectErrors es a) $t       where       type MinMaxType (CollectErrors es  a) $t =-        EnsureCE es (MinMaxType a $t)-      min = lift2TCE min-      max = lift2TCE max+        CollectErrors es (MinMaxType a $t)+      min = CE.lift1T min+      max = CE.lift1T max    |]))  -{-| Compound type constraint useful for test definition. -}-type CanNegX t =-  (CanNeg t, Show t, Arbitrary t, Show (NegType t))- {----  numeric negation tests and instances -----}  {-|   HSpec properties that each numeric implementation of CanNeg should satisfy.  -} specCanNegNum ::-  (CanNegX t, CanNegX (NegType t),-   HasEqCertainly t (NegType (NegType t)),-   ConvertibleExactly Integer t,-   HasEqCertainly t t,-   HasEqCertainly t (NegType t),-   CanTestFinite t,-   CanTestPosNeg t,-   CanTestPosNeg (NegType t)-  )-  =>-  T t -> Spec+  _ => T t -> Spec specCanNegNum (T typeName :: T t) =   describe (printf "CanNeg %s" typeName) $ do     it "ignores double negation" $ do@@ -352,32 +278,18 @@ instance CanAbs Double  instance-  (CanAbs a-  , CanEnsureCE es a-  , CanEnsureCE es (AbsType a)-  , SuitableForCE es)+  (CanAbs a, CanBeErrors es)   =>   CanAbs (CollectErrors es a)   where-  type AbsType (CollectErrors es a) = EnsureCE es (AbsType a)-  abs = lift1CE abs--type CanAbsX t =-  (CanAbs t,-   CanNegSameType t,-   CanTestPosNeg t,-   CanTestPosNeg (AbsType t),-   HasEqCertainly t t,-   HasEqCertainly t (AbsType t),-   Show t, Arbitrary t, Show (AbsType t))+  type AbsType (CollectErrors es a) = CollectErrors es (AbsType a)+  abs = CE.lift abs  {-|   HSpec properties that each implementation of CanAbs should satisfy.  -} specCanAbs ::-  (CanAbsX t, CanAbsX (AbsType t), CanTestFinite t)-  =>-  T t -> Spec+  _ => T t -> Spec specCanAbs (T typeName :: T t) =   describe (printf "CanAbs %s" typeName) $ do     it "is idempotent" $ do
src/Numeric/MixedTypes/Ord.hs view
@@ -1,3 +1,5 @@+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE TemplateHaskell #-} {-|     Module      :  Numeric.MixedType.Ord@@ -16,7 +18,6 @@   -- * Comparisons in numeric order   HasOrder, HasOrderAsymmetric(..), (>), (<), (<=), (>=)   , HasOrderCertainlyAsymmetric, HasOrderCertainly-  , HasOrderCertainlyCE, HasOrderCertainlyCN   , (?<=?), (?<?), (?>=?), (?>?)   , (!<=!), (!<!), (!>=!), (!>!)   -- ** Tests@@ -35,8 +36,8 @@ import Test.Hspec import qualified Test.QuickCheck as QC -import Numeric.CollectErrors-import Control.CollectErrors+import Control.CollectErrors ( CollectErrors, CanBeErrors )+import qualified Control.CollectErrors as CE  import Numeric.MixedTypes.Literals import Numeric.MixedTypes.Bool@@ -55,19 +56,6 @@ type HasOrderCertainly t1 t2 =   (HasOrder t1 t2, CanTestCertainly (OrderCompareType t1 t2)) -type HasOrderCertainlyCE es t1 t2 =-  (HasOrderCertainly t1 t2,-   HasOrderCertainly (EnsureCE es t1) (EnsureCE es t2))-  --  ,-  --  CanTestCertainly (WithoutCE es (OrderCompareType (WithoutCE es t1) (WithoutCE es t2))),-  --  IsBool (WithoutCE es (OrderCompareType (WithoutCE es t1) (WithoutCE es t2))),-  --  CanEnsureCE es (OrderCompareType (WithoutCE es t1) (WithoutCE es t2)),-  --  CanEnsureCE es (WithoutCE es (OrderCompareType (WithoutCE es t1) (WithoutCE es t2))),-  --  WithoutCE es (WithoutCE es (OrderCompareType (WithoutCE es t1) (WithoutCE es t2)))-  --    ~ (WithoutCE es (OrderCompareType (WithoutCE es t1) (WithoutCE es t2))))--type HasOrderCertainlyCN t1 t2 = HasOrderCertainlyCE NumErrors t1 t2- type HasOrderCertainlyAsymmetric t1 t2 =   (HasOrderAsymmetric t1 t2, CanTestCertainly (OrderCompareType t1 t2)) @@ -131,19 +119,7 @@   HSpec properties that each implementation of 'HasOrder' should satisfy.  -} specHasOrder ::-  (Show t1, Show t2, Show t3, QC.Arbitrary t1, QC.Arbitrary t2,-   QC.Arbitrary t3, CanTestCertainly (OrderCompareType t1 t1),-   CanTestCertainly (OrderCompareType t1 t2),-   CanTestCertainly (OrderCompareType t2 t1),-   CanTestCertainly (OrderCompareType t2 t3),-   CanTestCertainly-     (AndOrType (OrderCompareType t1 t2) (OrderCompareType t2 t3)),-   CanAndOrAsymmetric-     (OrderCompareType t1 t2) (OrderCompareType t2 t3),-   HasOrderAsymmetric t1 t1, HasOrderAsymmetric t1 t2,-   HasOrderAsymmetric t2 t1, HasOrderAsymmetric t2 t3)-  =>-  T t1 -> T t2 -> T t3 -> Spec+  _ => T t1 -> T t2 -> T t3 -> Spec specHasOrder (T typeName1 :: T t1) (T typeName2 :: T t2) (T typeName3 :: T t3) =   describe (printf "HasOrd %s %s, HasOrd %s %s" typeName1 typeName2 typeName2 typeName3) $ do     it "has reflexive >=" $ do@@ -169,12 +145,7 @@   HSpec properties that each implementation of 'HasOrder' should satisfy.  -} specHasOrderNotMixed ::-  (Show t, QC.Arbitrary t, CanTestCertainly (OrderCompareType t t),-   CanTestCertainly-     (AndOrType (OrderCompareType t t) (OrderCompareType t t)),-   HasOrderAsymmetric t t)-  =>-  T t -> Spec+  _ => T t -> Spec specHasOrderNotMixed (t :: T t) = specHasOrder t t t  instance HasOrderAsymmetric () () where@@ -222,56 +193,44 @@   leq d n = leq d (integer n)  instance-  (HasOrderAsymmetric a b-  , CanEnsureCE es a, CanEnsureCE es b-  , CanEnsureCE es (OrderCompareType a b)-  , IsBool (EnsureCE es (OrderCompareType a b))-  , SuitableForCE es)+  (HasOrderAsymmetric a b, CanBeErrors es)   =>   HasOrderAsymmetric (CollectErrors es a) (CollectErrors es b)   where   type OrderCompareType (CollectErrors es a) (CollectErrors es b) =-    EnsureCE es (OrderCompareType a b)-  lessThan = lift2CE lessThan-  leq = lift2CE leq-  greaterThan = lift2CE greaterThan-  geq = lift2CE geq+    CollectErrors es (OrderCompareType a b)+  lessThan = CE.lift2 lessThan+  leq = CE.lift2 leq+  greaterThan = CE.lift2 greaterThan+  geq = CE.lift2 geq  $(declForTypes   [[t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]   (\ t -> [d|      instance-      (HasOrderAsymmetric $t b-      , CanEnsureCE es b-      , CanEnsureCE es (OrderCompareType $t b)-      , IsBool (EnsureCE es (OrderCompareType $t b))-      , SuitableForCE es)+      (HasOrderAsymmetric $t b, CanBeErrors es)       =>       HasOrderAsymmetric $t (CollectErrors es  b)       where       type OrderCompareType $t (CollectErrors es  b) =-        EnsureCE es (OrderCompareType $t b)-      lessThan = lift2TLCE lessThan-      leq = lift2TLCE leq-      greaterThan = lift2TLCE greaterThan-      geq = lift2TLCE geq+        CollectErrors es (OrderCompareType $t b)+      lessThan = CE.liftT1 lessThan+      leq = CE.liftT1 leq+      greaterThan = CE.liftT1 greaterThan+      geq = CE.liftT1 geq      instance-      (HasOrderAsymmetric a $t-      , CanEnsureCE es a-      , CanEnsureCE es (OrderCompareType a $t)-      , IsBool (EnsureCE es (OrderCompareType a $t))-      , SuitableForCE es)+      (HasOrderAsymmetric a $t, CanBeErrors es)       =>       HasOrderAsymmetric (CollectErrors es a) $t       where       type OrderCompareType (CollectErrors es  a) $t =-        EnsureCE es (OrderCompareType a $t)-      lessThan = lift2TCE lessThan-      leq = lift2TCE leq-      greaterThan = lift2TCE greaterThan-      geq = lift2TCE geq+        CollectErrors es (OrderCompareType a $t)+      lessThan = CE.lift1T lessThan+      leq = CE.lift1T leq+      greaterThan = CE.lift1T greaterThan+      geq = CE.lift1T geq    |])) @@ -294,8 +253,8 @@ instance CanTestPosNeg Rational instance CanTestPosNeg Double -instance (CanTestPosNeg t, SuitableForCE es) => (CanTestPosNeg (CollectErrors es t)) where-  isCertainlyPositive ce = getValueIfNoErrorCE ce isCertainlyPositive (const False)-  isCertainlyNonNegative ce = getValueIfNoErrorCE ce isCertainlyNonNegative (const False)-  isCertainlyNegative ce = getValueIfNoErrorCE ce isCertainlyNegative (const False)-  isCertainlyNonPositive ce = getValueIfNoErrorCE ce isCertainlyNonPositive (const False)+instance (CanTestPosNeg t, CanBeErrors es) => (CanTestPosNeg (CollectErrors es t)) where+  isCertainlyPositive = CE.withErrorOrValue (const False) isCertainlyPositive+  isCertainlyNonNegative = CE.withErrorOrValue (const False) isCertainlyNonNegative+  isCertainlyNegative = CE.withErrorOrValue (const False) isCertainlyNegative+  isCertainlyNonPositive = CE.withErrorOrValue (const False) isCertainlyNonPositive
+ src/Numeric/MixedTypes/Power.hs view
@@ -0,0 +1,232 @@+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE TemplateHaskell #-}+{-|+    Module      :  Numeric.MixedType.Power+    Description :  Bottom-up typed exponentiation+    Copyright   :  (c) Michal Konecny+    License     :  BSD3++    Maintainer  :  mikkonecny@gmail.com+    Stability   :  experimental+    Portability :  portable++-}++module Numeric.MixedTypes.Power+(+  -- * Exponentiation+   CanPow(..), CanPowBy+  , (^)+  , powUsingMul, integerPowCN+  , powUsingMulRecip+  -- ** Tests+  , specCanPow+)+where++import Utils.TH.DeclForTypes++import Numeric.MixedTypes.PreludeHiding+import qualified Prelude as P+import Text.Printf++import Test.Hspec+import Test.QuickCheck++import Numeric.CollectErrors ( CN, cn )+import qualified Numeric.CollectErrors as CN++import Numeric.MixedTypes.Literals+import Numeric.MixedTypes.Bool+import Numeric.MixedTypes.Eq+import Numeric.MixedTypes.Ord+-- import Numeric.MixedTypes.MinMaxAbs+import Numeric.MixedTypes.AddSub+import Numeric.MixedTypes.Ring+import Numeric.MixedTypes.Div++++{---- Exponentiation -----}++infixl 8  ^++(^) :: (CanPow t1 t2) => t1 -> t2 -> PowType t1 t2+(^) = pow+++{-|+  A replacement for Prelude's binary `P.^` and `P.^^`.+-}+class CanPow b e where+  type PowType b e+  type PowType b e = b -- default+  pow :: b -> e -> PowType b e++integerPowCN ::+  (HasOrderCertainly b Integer, HasOrderCertainly e Integer,+   HasEqCertainly b Integer, HasEqCertainly e Integer)+  =>+  (b -> e -> r) -> CN b -> CN e -> CN r+integerPowCN unsafeIntegerPow b n+  | n !<! 0 =+    CN.noValueNumErrorCertain $ CN.OutOfDomain "illegal integer pow: negative exponent"+  | n !==! 0 && b !==! 0 =+    CN.noValueNumErrorCertain $ CN.OutOfDomain "illegal integer pow: 0^0"+  | n ?<? 0 =+    CN.noValueNumErrorCertain $ CN.OutOfDomain "illegal integer pow: negative exponent"+  | n ?==? 0 && b ?==? 0 =+    CN.noValueNumErrorPotential $ CN.OutOfDomain "illegal integer pow: 0^0"+  | otherwise =+    CN.lift2 unsafeIntegerPow b n++powCN ::+  (HasOrderCertainly b Integer, HasOrderCertainly e Integer,+   HasEqCertainly b Integer, CanTestInteger e)+  =>+  (b -> e -> r) -> CN b -> CN e -> CN r+powCN unsafePow b e+  | b !==! 0 && e !<=! 0 =+    CN.noValueNumErrorCertain $ CN.OutOfDomain "illegal pow: 0^e with e <= 0"+  | b !<! 0 && certainlyNotInteger e =+    CN.noValueNumErrorCertain $ CN.OutOfDomain "illegal pow: b^e with b < 0 and e non-integer"+  | b ?==? 0 && e ?<=? 0 =+    CN.noValueNumErrorPotential $ CN.OutOfDomain "illegal pow: 0^e with e <= 0"+  | b ?<? 0 && not (certainlyInteger e) =+    CN.noValueNumErrorPotential $ CN.OutOfDomain "illegal pow: b^e with b < 0 and e non-integer"+  | otherwise =+    CN.lift2 unsafePow b e++powUsingMul ::+  (CanBeInteger e,+   CanMulSameType t)+   =>+   t -> t -> e -> t+powUsingMul one x nPre+  | n < 0 = error $ "powUsingMul is not defined for negative exponent " ++ show n+  | n == 0 = one+  | otherwise = aux n+  where+    n = integer nPre+    aux m+      | m == 1 = x+      | even m =+        let s = aux (m `P.div` 2) in s * s+      | otherwise =+        let s = aux ((m-1) `P.div` 2) in x * s * s++powUsingMulRecip ::+  (CanBeInteger e, CanMulSameType b, CanRecipSameType b)+   =>+   b -> b -> e -> b+powUsingMulRecip one x e+  | eI < 0 = recip $ powUsingMul one x (negate eI)+  | otherwise = powUsingMul one x eI+  where+  eI = integer e++type CanPowBy t1 t2 =+  (CanPow t1 t2, PowType t1 t2 ~ t1)++{-|+  HSpec properties that each implementation of CanPow should satisfy.+ -}+specCanPow ::+  _ => T t1 -> T t2 -> Spec+specCanPow (T typeName1 :: T t1) (T typeName2 :: T t2) =+  describe (printf "CanPow %s %s" typeName1 typeName2) $ do+    it "x^0 = 1" $ do+      property $ \ (x :: t1) ->+        let one = (convertExactly 1 :: t1) in+        let z = (convertExactly 0 :: t2) in+        (x ^ z) ?==?$ one+    it "x^1 = x" $ do+      property $ \ (x :: t1) ->+        let one = (convertExactly 1 :: t2) in+        (x ^ one) ?==?$ x+    it "x^(y+1) = x*x^y" $ do+      property $ \ (x :: t1) (y :: t2) ->+        (isCertainlyNonNegative y) ==>+          x * (x ^ y) ?==?$ (x ^ (y + 1))+  where+  infix 4 ?==?$+  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property+  (?==?$) = printArgsIfFails2 "?==?" (?==?)++instance CanPow Integer Integer where  +  type PowType Integer Integer = Rational+  pow b = (P.^^) (rational b)+instance CanPow Integer Int where+  type PowType Integer Int = Rational+  pow b = (P.^^) (rational b)+instance CanPow Int Integer where+  type PowType Int Integer = Rational+  pow b = (P.^^) (rational b)+instance CanPow Int Int where+  type PowType Int Int = Rational+  pow b = (P.^^) (rational b)+instance CanPow Rational Int where+  pow = (P.^^)+instance CanPow Rational Integer where+  pow = (P.^^)+instance CanPow Double Int where+  pow = (P.^^)+instance CanPow Double Integer where+  pow = (P.^^)+instance CanPow Double Double where+  type PowType Double Double = Double+  pow = (P.**)+instance CanPow Double Rational where+  type PowType Double Rational = Double+  pow b e = b ^ (double e)+instance CanPow Rational Double where+  type PowType Rational Double = Double+  pow b e = (double b) ^ e+instance CanPow Integer Double where+  type PowType Integer Double = Double+  pow b e = (double b) ^ e+instance CanPow Int Double where+  type PowType Int Double = Double+  pow b e = (double b) ^ e++-- instance (CanPow a b) => CanPow [a] [b] where+--   type PowType [a] [b] = [PowType a b]+--   pow (x:xs) (y:ys) = (pow x y) : (pow xs ys)+--   pow _ _ = []++instance (CanPow a b) => CanPow (Maybe a) (Maybe b) where+  type PowType (Maybe a) (Maybe b) = Maybe (PowType a b)+  pow (Just x) (Just y) = Just (pow x y)+  pow _ _ = Nothing++instance+  (CanPow b e, HasOrderCertainly b Integer, HasOrderCertainly e Integer,+   HasEqCertainly b Integer, CanTestInteger e)+  =>+  CanPow (CN b) (CN e)+  where+  type PowType (CN b) (CN e) = CN (PowType b e)+  pow = powCN pow++$(declForTypes+  [[t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]+  (\ t -> [d|++    instance+      (CanPow $t e, HasOrderCertainly e Integer, CanTestInteger e)+      =>+      CanPow $t (CN e)+      where+      type PowType $t (CN e) = CN (PowType $t e)+      pow b e = powCN pow (cn b) e++    instance+      (CanPow b $t, HasOrderCertainly b Integer, HasEqCertainly b Integer)+      =>+      CanPow (CN b) $t+      where+      type PowType (CN b) $t = CN (PowType b $t)+      pow b e = powCN pow b (cn e)++  |]))
+ src/Numeric/MixedTypes/Reduce.hs view
@@ -0,0 +1,44 @@+{-|+    Module      :  Numeric.MixedType.Reduce+    Description :  Throw error when too inaccurate+    Copyright   :  (c) Michal Konecny+    License     :  BSD3++    Maintainer  :  mikkonecny@gmail.com+    Stability   :  experimental+    Portability :  portable++    Mechanism to throw an error when a value gets too inaccurate.+-}+module Numeric.MixedTypes.Reduce+(+    CanGiveUpIfVeryInaccurate(giveUpIfVeryInaccurate)+    , numErrorVeryInaccurate+)+where++import Numeric.MixedTypes.PreludeHiding+-- import qualified Prelude as P++import Numeric.CollectErrors ( CN, NumError (NumError) )++class CanGiveUpIfVeryInaccurate t where+  {-| If the value contains so little information that it is seen as useless,+      drop the value and add an error indicating what happened.+    -}+  giveUpIfVeryInaccurate :: CN t -> CN t+  giveUpIfVeryInaccurate = id  -- by default, never give up!++numErrorVeryInaccurate :: String -> String -> NumError+numErrorVeryInaccurate context detail =+  case (context, detail) of+     ("", "") -> NumError $ msg <> "."+     ("", _) -> NumError $ msg <> ": " ++ detail+     (_, "") -> NumError $ context <> ": " <> msg <> "."+     _ -> NumError $ context <> ": " <> msg <> ": " ++ detail+  where+  msg = "Very inaccurate, too little information"++instance CanGiveUpIfVeryInaccurate Int+instance CanGiveUpIfVeryInaccurate Integer+instance CanGiveUpIfVeryInaccurate Rational
src/Numeric/MixedTypes/Ring.hs view
@@ -1,7 +1,9 @@+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE TemplateHaskell #-} {-|     Module      :  Numeric.MixedType.Ring-    Description :  Bottom-up typed multiplication and exponent+    Description :  Bottom-up typed multiplication with ring laws     Copyright   :  (c) Michal Konecny     License     :  BSD3 @@ -20,12 +22,6 @@   , (*), product   -- ** Tests   , specCanMul, specCanMulNotMixed, specCanMulSameType-  -- * Exponentiation-  , CanPow(..), CanPowBy, CanPowCNBy-  , (^), (^!)-  , powUsingMul, integerPowCN-  -- ** Tests-  , specCanPow ) where @@ -40,8 +36,8 @@ import Test.Hspec import Test.QuickCheck -import Numeric.CollectErrors-import Control.CollectErrors+import qualified Numeric.CollectErrors as CN+import Numeric.CollectErrors ( CN )  import Numeric.MixedTypes.Literals import Numeric.MixedTypes.Bool@@ -49,26 +45,19 @@ import Numeric.MixedTypes.Ord -- import Numeric.MixedTypes.MinMaxAbs import Numeric.MixedTypes.AddSub+import Numeric.MixedTypes.Reduce  {----- Ring -----}  type CanAddSubMulBy t s =   (CanAddThis t s, CanSubThis t s, CanSub s t, SubType s t ~ t, CanMulBy t s) -type RingPre t =+class   (CanNegSameType t, CanAddSameType t, CanSubSameType t, CanMulSameType t,-   CanPowCNBy t Integer, CanPowCNBy t Int,    HasEq t t,    HasEq t Integer, CanAddSubMulBy t Integer,    HasEq t Int, CanAddSubMulBy t Int,-   HasIntegers t)--class-  (RingPre t,-   CanEnsureCN t,-   RingPre (EnsureCN t))-  =>-  Ring t+   HasIntegers t) => Ring t  instance Ring Integer instance Ring (CN Integer)@@ -78,15 +67,9 @@ class   (Ring t   , HasEq t t-  , HasEq (EnsureCN t) t-  , HasEq t (EnsureCN t)   , HasEq t Int, HasEq t Integer-  , HasEq (EnsureCN t) Int, HasEq (EnsureCN t) Integer   , HasOrder t t-  , HasOrder (EnsureCN t) t-  , HasOrder t (EnsureCN t)-  , HasOrder t Int, HasOrder t Integer-  , HasOrder (EnsureCN t) Int, HasOrder (EnsureCN t) Integer)+  , HasOrder t Int, HasOrder t Integer)   => OrderedRing t  instance OrderedRing Integer@@ -97,15 +80,9 @@ class   (Ring t   , HasEqCertainly t t-  , HasEqCertainly (EnsureCN t) t-  , HasEqCertainly t (EnsureCN t)   , HasEqCertainly t Int, HasEq t Integer-  , HasEqCertainly (EnsureCN t) Int, HasEq (EnsureCN t) Integer   , HasOrderCertainly t t-  , HasOrderCertainly (EnsureCN t) t-  , HasOrderCertainly t (EnsureCN t)   , HasOrderCertainly t Int, HasOrderCertainly t Integer-  , HasOrderCertainly (EnsureCN t) Int, HasOrderCertainly (EnsureCN t) Integer   , CanTestPosNeg t)   => OrderedCertainlyRing t @@ -131,7 +108,6 @@   default mul :: (MulType t1 t2 ~ t1, t1~t2, P.Num t1) => t1 -> t2 -> MulType t1 t2   mul = (P.*) -infixl 8  ^, ^! infixl 7  *  (*) :: (CanMulAsymmetric t1 t2) => t1 -> t2 -> MulType t1 t2@@ -149,36 +125,7 @@   HSpec properties that each implementation of CanMul should satisfy.  -} specCanMul ::-  (Show t1, Show t2, Show t3, Show (MulType t1 t2),-   Show (MulType t2 t1), Show (MulType t1 (MulType t2 t3)),-   Show (MulType (MulType t1 t2) t3),-   Show (MulType t1 (AddType t2 t3)),-   Show (AddType (MulType t1 t2) (MulType t1 t3)), Arbitrary t1,-   Arbitrary t2, Arbitrary t3, ConvertibleExactly Integer t2,-   CanTestCertainly (EqCompareType (MulType t1 t2) t1),-   CanTestCertainly (EqCompareType (MulType t1 t2) (MulType t2 t1)),-   CanTestCertainly-     (EqCompareType-        (MulType t1 (MulType t2 t3)) (MulType (MulType t1 t2) t3)),-   CanTestCertainly-     (EqCompareType-        (MulType t1 (AddType t2 t3))-        (AddType (MulType t1 t2) (MulType t1 t3))),-   HasEqAsymmetric (MulType t1 t2) t1,-   HasEqAsymmetric (MulType t1 t2) (MulType t2 t1),-   HasEqAsymmetric-     (MulType t1 (MulType t2 t3)) (MulType (MulType t1 t2) t3),-   HasEqAsymmetric-     (MulType t1 (AddType t2 t3))-     (AddType (MulType t1 t2) (MulType t1 t3)),-   CanAddAsymmetric t2 t3,-   CanAddAsymmetric (MulType t1 t2) (MulType t1 t3),-   CanMulAsymmetric t1 t2, CanMulAsymmetric t1 t3,-   CanMulAsymmetric t1 (MulType t2 t3),-   CanMulAsymmetric t1 (AddType t2 t3), CanMulAsymmetric t2 t1,-   CanMulAsymmetric t2 t3, CanMulAsymmetric (MulType t1 t2) t3)-  =>-  T t1 -> T t2 -> T t3 -> Spec+  _ => T t1 -> T t2 -> T t3 -> Spec specCanMul (T typeName1 :: T t1) (T typeName2 :: T t2) (T typeName3 :: T t3) =   describe (printf "CanMul %s %s, CanMul %s %s" typeName1 typeName2 typeName2 typeName3) $ do     it "absorbs 1" $ do@@ -200,30 +147,7 @@   HSpec properties that each implementation of CanMul should satisfy.  -} specCanMulNotMixed ::-  (Show t, Show (MulType t t), Show (MulType t (MulType t t)),-   Show (MulType (MulType t t) t), Show (MulType t (AddType t t)),-   Show (AddType (MulType t t) (MulType t t)), Arbitrary t,-   ConvertibleExactly Integer t,-   CanTestCertainly (EqCompareType (MulType t t) t),-   CanTestCertainly (EqCompareType (MulType t t) (MulType t t)),-   CanTestCertainly-     (EqCompareType-        (MulType t (MulType t t)) (MulType (MulType t t) t)),-   CanTestCertainly-     (EqCompareType-        (MulType t (AddType t t)) (AddType (MulType t t) (MulType t t))),-   HasEqAsymmetric (MulType t t) t,-   HasEqAsymmetric (MulType t t) (MulType t t),-   HasEqAsymmetric-     (MulType t (MulType t t)) (MulType (MulType t t) t),-   HasEqAsymmetric-     (MulType t (AddType t t)) (AddType (MulType t t) (MulType t t)),-   CanAddAsymmetric t t, CanAddAsymmetric (MulType t t) (MulType t t),-   CanMulAsymmetric t t, CanMulAsymmetric t (MulType t t),-   CanMulAsymmetric t (AddType t t),-   CanMulAsymmetric (MulType t t) t)-  =>-  T t -> Spec+  _ => T t -> Spec specCanMulNotMixed (t :: T t) = specCanMul t t t  {-|@@ -307,267 +231,30 @@   mul _ _ = Nothing  instance-  (CanMulAsymmetric a b-  , CanEnsureCE es a, CanEnsureCE es b-  , CanEnsureCE es (MulType a b)-  , SuitableForCE es)-  =>-  CanMulAsymmetric (CollectErrors es a) (CollectErrors es  b)-  where-  type MulType (CollectErrors es a) (CollectErrors es b) =-    EnsureCE es (MulType a b)-  mul = lift2CE mul--{---- Exponentiation -----}--(^) :: (CanPow t1 t2) => t1 -> t2 -> PowType t1 t2-(^) = pow--{-| Like `^` but throwing an exception if the power is undefined. -}-(^!) :: (CanPow t1 t2) =>-  t1 -> t2 -> PowTypeNoCN t1 t2-(^!) = powNoCN---{-|-  A replacement for Prelude's binary `P.^` and `P.^^`.  If @Num t1@ and @Integral t2@,-  then one can use the default implementation to mirror Prelude's @^@.--}-class CanPow b e where-  type PowTypeNoCN b e-  type PowTypeNoCN b e = b -- default-  powNoCN :: b -> e -> PowTypeNoCN b e-  type PowType b e-  type PowType b e = EnsureCN (PowTypeNoCN b e) -- default-  pow :: b -> e -> PowType b e-  default pow ::-    (HasOrderCertainly b Integer, HasOrderCertainly e Integer,-     HasEqCertainly b Integer, CanTestInteger e,-     CanEnsureCN (PowTypeNoCN b e), PowType b e~EnsureCN (PowTypeNoCN b e))-    =>-    b -> e -> PowType b e-  pow = powCN powNoCN--integerPowCN ::-  (HasOrderCertainly b Integer, HasOrderCertainly e Integer,-   HasEqCertainly b Integer, HasEqCertainly e Integer,-   CanEnsureCN r)-  =>-  (b -> e -> r) -> b -> e -> EnsureCN r-integerPowCN unsafeIntegerPow b n-  | n !<! 0 =-    noValueNumErrorCertainECN sample_v $ OutOfRange "illegal integer pow: negative exponent"-  | n !==! 0 && b !==! 0 =-    noValueNumErrorCertainECN sample_v $ OutOfRange "illegal integer pow: 0^0"-  | n ?<? 0 =-    noValueNumErrorPotentialECN sample_v $ OutOfRange "illegal integer pow: negative exponent"-  | n ?==? 0 && b ?==? 0 =-    noValueNumErrorPotentialECN sample_v $ OutOfRange "illegal integer pow: 0^0"-  | otherwise =-    ensureCN $ unsafeIntegerPow b n-  where-  sample_v = Just (unsafeIntegerPow b n)--powCN ::-  (HasOrderCertainly b Integer, HasOrderCertainly e Integer,-   HasEqCertainly b Integer, CanTestInteger e,-   CanEnsureCN r)-  =>-  (b -> e -> r) -> b -> e -> EnsureCN r-powCN unsafePow b e-  | b !==! 0 && e !<=! 0 =-    noValueNumErrorCertainECN sample_v $ OutOfRange "illegal pow: 0^e with e <= 0"-  | b !<! 0 && certainlyNotInteger e =-    noValueNumErrorCertainECN sample_v $ OutOfRange "illegal pow: b^e with b < 0 and e non-integer"-  | b ?==? 0 && e ?<=? 0 =-    noValueNumErrorPotentialECN sample_v $ OutOfRange "illegal pow: 0^e with e <= 0"-  | b ?<? 0 && not (certainlyInteger e) =-    noValueNumErrorPotentialECN sample_v $ OutOfRange "illegal pow: b^e with b < 0 and e non-integer"-  | otherwise =-    ensureCN $ unsafePow b e-  where-  sample_v = Just (unsafePow b e)--powUsingMul ::-  (CanBeInteger e,-   CanMulSameType t)-   =>-   t -> t -> e -> t-powUsingMul one x nPre-  | n < 0 = error $ "powUsingMul is not defined for negative exponent " ++ show n-  | n == 0 = one-  | otherwise = aux n-  where-    n = integer nPre-    aux m-      | m == 1 = x-      | even m =-        let s = aux (m `P.div` 2) in s * s-      | otherwise =-        let s = aux ((m-1) `P.div` 2) in x * s * s--type CanPowBy t1 t2 =-  (CanPow t1 t2, PowType t1 t2 ~ t1, PowTypeNoCN t1 t2 ~ t1)--type CanPowCNBy t1 t2 =-  (CanPow t1 t2, PowType t1 t2 ~ EnsureCN t1, PowTypeNoCN t1 t2 ~ t1-  , CanEnsureCN t1-  , CanPow (EnsureCN t1) t2, PowType (EnsureCN t1) t2 ~ EnsureCN t1-  , PowTypeNoCN (EnsureCN t1) t2 ~ (EnsureCN t1))--{-|-  HSpec properties that each implementation of CanPow should satisfy.- -}-specCanPow ::-  (Show t1, Show t2, Show (PowType t1 t2),-   Show (MulType t1 (PowType t1 t2)),-   Show (PowType t1 (AddType t2 Integer)), Arbitrary t1, Arbitrary t2,-   ConvertibleExactly Integer t1, ConvertibleExactly Integer t2,-   CanTestCertainly (EqCompareType (PowType t1 t2) t1),-   CanTestCertainly-     (EqCompareType-        (MulType t1 (PowType t1 t2)) (PowType t1 (AddType t2 Integer))),-   HasEqAsymmetric (PowType t1 t2) t1,-   HasEqAsymmetric-     (MulType t1 (PowType t1 t2)) (PowType t1 (AddType t2 Integer)),-   CanTestPosNeg t2, CanAddAsymmetric t2 Integer, CanPow t1 t2,-   CanPow t1 (AddType t2 Integer),-   CanMulAsymmetric t1 (PowType t1 t2))-  =>-  T t1 -> T t2 -> Spec-specCanPow (T typeName1 :: T t1) (T typeName2 :: T t2) =-  describe (printf "CanPow %s %s" typeName1 typeName2) $ do-    it "x^0 = 1" $ do-      property $ \ (x :: t1) ->-        let one = (convertExactly 1 :: t1) in-        let z = (convertExactly 0 :: t2) in-        (x ^ z) ?==?$ one-    it "x^1 = x" $ do-      property $ \ (x :: t1) ->-        let one = (convertExactly 1 :: t2) in-        (x ^ one) ?==?$ x-    it "x^(y+1) = x*x^y" $ do-      property $ \ (x :: t1) (y :: t2) ->-        (isCertainlyNonNegative y) ==>-          x * (x ^ y) ?==?$ (x ^ (y + 1))-  where-  infix 4 ?==?$-  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property-  (?==?$) = printArgsIfFails2 "?==?" (?==?)--instance CanPow Integer Integer where-  powNoCN = (P.^)-  pow = integerPowCN (P.^)-instance CanPow Integer Int where-  powNoCN = (P.^)-  pow = integerPowCN (P.^)-instance CanPow Int Integer where-  type PowTypeNoCN Int Integer = Integer-  powNoCN x n = powNoCN (integer x) n-  pow x n = pow (integer x) n-instance CanPow Int Int where-  type PowTypeNoCN Int Int = Integer-  powNoCN x n = powNoCN (integer x) n-  pow x n = pow (integer x) n-instance CanPow Rational Int where-  powNoCN = (P.^^)-instance CanPow Rational Integer where-  powNoCN = (P.^^)-instance CanPow Double Int where-  powNoCN = (P.^^)-  type PowType Double Int = Double-  pow = (P.^^)-instance CanPow Double Integer where-  powNoCN = (P.^^)-  type PowType Double Integer = Double-  pow = (P.^^)---- instance (CanPow a b) => CanPow [a] [b] where---   type PowType [a] [b] = [PowType a b]---   pow (x:xs) (y:ys) = (pow x y) : (pow xs ys)---   pow _ _ = []--instance (CanPow a b) => CanPow (Maybe a) (Maybe b) where-  type PowTypeNoCN (Maybe a) (Maybe b) = Maybe (PowTypeNoCN a b)-  powNoCN (Just x) (Just y) = Just (powNoCN x y)-  powNoCN _ _ = Nothing-  type PowType (Maybe a) (Maybe b) = Maybe (PowType a b)-  pow (Just x) (Just y) = Just (pow x y)-  pow _ _ = Nothing--instance-  (CanPow a b-  , CanEnsureCE es a, CanEnsureCE es b-  , CanEnsureCE es (PowTypeNoCN a b)-  , CanEnsureCE es (PowType a b)-  , SuitableForCE es)+  (CanMulAsymmetric a b, CanGiveUpIfVeryInaccurate (MulType a b))   =>-  CanPow (CollectErrors es a) (CollectErrors es  b)+  CanMulAsymmetric (CN a) (CN b)   where-  type PowTypeNoCN (CollectErrors es a) (CollectErrors es b) =-    EnsureCE es (PowTypeNoCN a b)-  powNoCN = lift2CE powNoCN-  type PowType (CollectErrors es a) (CollectErrors es b) =-    EnsureCE es (PowType a b)-  pow = lift2CE pow+  type MulType (CN a) (CN b) = CN (MulType a b)+  mul a b = giveUpIfVeryInaccurate $ CN.lift2 mul a b  $(declForTypes   [[t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]   (\ t -> [d|      instance-      (CanPow $t b-      , CanEnsureCE es b-      , CanEnsureCE es (PowType $t b)-      , CanEnsureCE es (PowTypeNoCN $t b)-      , SuitableForCE es)-      =>-      CanPow $t (CollectErrors es  b)-      where-      type PowTypeNoCN $t (CollectErrors es  b) =-        EnsureCE es (PowTypeNoCN $t b)-      powNoCN = lift2TLCE powNoCN-      type PowType $t (CollectErrors es  b) =-        EnsureCE es (PowType $t b)-      pow = lift2TLCE pow--    instance-      (CanPow a $t-      , CanEnsureCE es a-      , CanEnsureCE es (PowType a $t)-      , CanEnsureCE es (PowTypeNoCN a $t)-      , SuitableForCE es)-      =>-      CanPow (CollectErrors es a) $t-      where-      type PowTypeNoCN (CollectErrors es  a) $t =-        EnsureCE es (PowTypeNoCN a $t)-      powNoCN = lift2TCE powNoCN-      type PowType (CollectErrors es  a) $t =-        EnsureCE es (PowType a $t)-      pow = lift2TCE pow--    instance-      (CanMulAsymmetric $t b-      , CanEnsureCE es b-      , CanEnsureCE es (MulType $t b)-      , SuitableForCE es)+      (CanMulAsymmetric $t b, CanGiveUpIfVeryInaccurate (MulType $t b))       =>-      CanMulAsymmetric $t (CollectErrors es  b)+      CanMulAsymmetric $t (CN b)       where-      type MulType $t (CollectErrors es  b) =-        EnsureCE es (MulType $t b)-      mul = lift2TLCE mul+      type MulType $t (CN b) = CN (MulType $t b)+      mul a b = giveUpIfVeryInaccurate $ CN.liftT1 mul a b      instance-      (CanMulAsymmetric a $t-      , CanEnsureCE es a-      , CanEnsureCE es (MulType a $t)-      , SuitableForCE es)+      (CanMulAsymmetric a $t, CanGiveUpIfVeryInaccurate (MulType a $t))       =>-      CanMulAsymmetric (CollectErrors es a) $t+      CanMulAsymmetric (CN a) $t       where-      type MulType (CollectErrors es  a) $t =-        EnsureCE es (MulType a $t)-      mul = lift2TCE mul+      type MulType (CN a) $t = CN (MulType a $t)+      mul a b = giveUpIfVeryInaccurate $ CN.lift1T mul a b   |]))
src/Numeric/MixedTypes/Round.hs view
@@ -1,3 +1,6 @@+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE TemplateHaskell #-} {-|     Module      :  Numeric.MixedType.Round     Description :  Bottom-up typed round, floor, etc.@@ -13,7 +16,9 @@ module Numeric.MixedTypes.Round (   -- * Rounded division + modulus-  CanDivIMod(..), CanDivIModIntegerSameType, modNoCN, divINoCN, divIModNoCN+  CanDivIMod(..)+  , CanDivIModIntegerSameType+  , CanDivIModIntegerSameTypeCN   -- * Rounding   , CanRound(..), HasIntegerBounds(..)   -- ** Tests@@ -21,6 +26,8 @@ ) where +import Utils.TH.DeclForTypes+ import Numeric.MixedTypes.PreludeHiding import qualified Prelude as P import Text.Printf@@ -31,8 +38,8 @@ import Test.Hspec import Test.QuickCheck as QC -import Numeric.CollectErrors--- import Control.CollectErrors+import Numeric.CollectErrors ( CN )+import qualified Numeric.CollectErrors as CN  import Numeric.MixedTypes.Literals import Numeric.MixedTypes.Bool@@ -46,9 +53,8 @@  class CanDivIMod t1 t2 where   type DivIType t1 t2-  type DivIType t1 t2 = CN Integer   type ModType t1 t2-  type ModType t1 t2 = EnsureCN t1+  type ModType t1 t2 = t1   divIMod :: t1 -> t2 -> (DivIType t1 t2, ModType t1 t2)   mod :: t1 -> t2 -> ModType t1 t2   mod a b = snd $ divIMod a b@@ -56,102 +62,89 @@   divI a b = fst $ divIMod a b  type CanDivIModIntegerSameType t =-  (CanDivIMod t t, CanEnsureCN t, DivIType t t ~ CN Integer, ModType t t ~ EnsureCN t)--modNoCN :: -  (CanDivIMod t1 t2-  , ModType t1 t2 ~ EnsureCN t1, CanEnsureCN t1)-  => -  t1 -> t2 -> t1-modNoCN x m = -  case deEnsureCN $ x `mod` m of-    Left err -> error $ show err-    Right xm -> xm--divINoCN :: -  (CanDivIMod t1 t2, DivIType t1 t2 ~ CN Integer)-  => -  t1 -> t2 -> Integer-divINoCN x m = (~!) $ x `divI` m+  (CanDivIMod t t, DivIType t t ~ Integer, ModType t t ~ t) -divIModNoCN :: -  (CanDivIMod t1 t2-  , ModType t1 t2 ~ EnsureCN t1, CanEnsureCN t1-  , DivIType t1 t2 ~ CN Integer)-  => -  t1 -> t2 -> (Integer, t1)-divIModNoCN x m = -  case deEnsureCN xm of-    Left err -> error $ show err-    Right xm2 -> ((~!) d, xm2)-  where-  (d,xm) = divIMod x m+type CanDivIModIntegerSameTypeCN t =+  (CanDivIMod t t, DivIType t t ~ CN Integer, ModType t t ~ t)  instance CanDivIMod Integer Integer where-  divIMod x m -    | m > 0 = (cn d, cn xm)-    | otherwise = (err, err)+  type DivIType Integer Integer = Integer+  divIMod = P.divMod++instance (CanDivIMod t1 t2, CanTestPosNeg t2) => CanDivIMod (CN t1) (CN t2) where+  type DivIType (CN t1) (CN t2) = (CN (DivIType t1 t2))+  type ModType (CN t1) (CN t2) = (CN (ModType t1 t2))+  divIMod x m+    | isCertainlyPositive m = (d, xm)+    | isCertainlyNegative m = (noval, noval)+    | otherwise = (errPote d, errPote xm)     where-    (d,xm) = P.divMod x m-    err = noValueNumErrorCertainECN sample_v $ OutOfRange $ "modulus not positive: " ++ show m-    sample_v = Just x+    (d,xm) = CN.lift2pair divIMod x m +noval :: CN v+noval = CN.noValueNumErrorCertain err+errPote :: CN t -> CN t+errPote = CN.prependErrorPotential err+err :: CN.NumError+err = CN.OutOfDomain "divIMod: modulus not positive"++$(declForTypes+  [[t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]+  (\ t -> [d|++    instance (CanDivIMod t1 $t) => CanDivIMod (CN t1) $t where+      type DivIType (CN t1) $t = (CN (DivIType t1 $t))+      type ModType (CN t1) $t = (CN (ModType t1 $t))+      divIMod x m+        | isCertainlyPositive m = (d, xm)+        | isCertainlyNegative m = (noval, noval)+        | otherwise = (errPote d, errPote xm)+        where+        (d,xm) = CN.lift1Tpair divIMod x m++    instance (CanDivIMod $t t2, CanTestPosNeg t2) => CanDivIMod $t (CN t2) where+      type DivIType $t (CN t2) = (CN (DivIType $t t2))+      type ModType $t (CN t2) = (CN (ModType $t t2))+      divIMod x m+        | isCertainlyPositive m = (d, xm)+        | isCertainlyNegative m = (noval, noval)+        | otherwise = (errPote d, errPote xm)+        where+        (d,xm) = CN.liftT1pair divIMod x m+  |]))+ instance CanDivIMod Rational Rational where-  divIMod x m -    | m > 0 = (cn d, cn xm)-    | otherwise = (err (d :: Integer), err xm)-    where-    (d,xm) = divMod' x m-    err :: (CanEnsureCN t) => t -> EnsureCN t-    err s = noValueNumErrorCertainECN (Just s) $ OutOfRange $ "modulus not positive: " ++ show m+  type DivIType Rational Rational = Integer+  divIMod = divMod'  instance CanDivIMod Rational Integer where+  type DivIType Rational Integer = Integer   divIMod x m = divIMod x (rational m)  instance CanDivIMod Double Double where-  divIMod x m -    | m > 0 = (cn d, cn xm)-    | otherwise = (err (d :: Integer), err xm)-    where-    (d,xm) = divMod' x m-    err :: (CanEnsureCN t) => t -> EnsureCN t-    err s = noValueNumErrorCertainECN (Just s) $ OutOfRange $ "modulus not positive: " ++ show m+  type DivIType Double Double = Integer+  divIMod = divMod'  instance CanDivIMod Double Integer where+  type DivIType Double Integer = Integer   divIMod x m = divIMod x (double m) -type CanDivIModX t =-  (CanDivIMod t t,-   ModType t t ~ EnsureCN t,-   DivIType t t ~ CN Integer,-   EnsureNoCN t ~ t,-   CanEnsureCN t,-   CanMulBy t Integer,-   CanAddSameType t,-   HasOrderCertainly t Integer,-   HasOrderCertainly t t,-   HasEqCertainly t t,-   CanTestFinite t,-   Show t, Arbitrary t)- {-|   HSpec properties that each implementation of CanRound should satisfy.  -} specCanDivIMod ::-  (CanDivIModX t, HasIntegers t)-  =>-  T t -> Spec+  _ => T t -> Spec specCanDivIMod (T typeName :: T t) =   describe (printf "CanDivMod %s %s" typeName typeName) $ do     it "holds 0 <= x `mod` m < m" $ do       property $ \ (x :: t)  (m :: t) ->         isFinite x && m !>! 0 ==>-          let xm = x `modNoCN` m in+          let xm = x `mod` m in           (0 ?<=?$ xm) .&&. (xm ?<?$ m)     it "holds x == (x `div'` m)*m + (x `mod` m)" $ do       property $ \ (x :: t)  (m :: t) ->         isFinite x && m !>! 0 ==>-          let (d,xm) = divIModNoCN x m in+          let (d,xm) = divIMod x m in           (x ?==?$ (d*m + xm))   where   (?<=?$) :: (HasOrderCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property@@ -173,13 +166,15 @@   In other cases, it is sufficient to define `properFraction`. -} class CanRound t where-  properFraction :: t -> (Integer, t)-  default properFraction :: (P.RealFrac t) => t -> (Integer, t)+  type RoundType t+  type RoundType t = Integer+  properFraction :: t -> (RoundType t, t)+  default properFraction :: (P.RealFrac t, RoundType t ~ Integer) => t -> (RoundType t, t)   properFraction = P.properFraction-  truncate :: t -> Integer+  truncate :: t -> RoundType t   truncate = fst . properFraction-  round :: t -> Integer-  default round :: (HasOrderCertainly t Rational) => t -> Integer+  round :: t -> RoundType t+  default round :: (HasOrderCertainly t Rational, RoundType t ~ Integer) => t -> RoundType t   round x     | -0.5 !<! r && r !<! 0.5 = n     | r !<! -0.5 = n - 1@@ -190,15 +185,15 @@     | otherwise = error "round default defn: Bad value"     where     (n,r) = properFraction x-  ceiling :: t -> Integer-  default ceiling :: (CanTestPosNeg t) => t -> Integer+  ceiling :: t -> RoundType t+  default ceiling :: (CanTestPosNeg t, RoundType t ~ Integer) => t -> RoundType t   ceiling x     | isCertainlyPositive r = n + 1     | otherwise = n     where     (n,r) = properFraction x-  floor :: t -> Integer-  default floor :: (CanTestPosNeg t) => t -> Integer+  floor :: t -> RoundType t+  default floor :: (CanTestPosNeg t, RoundType t ~ Integer) => t -> RoundType t   floor x     | isCertainlyNegative r = n - 1     | otherwise = n@@ -211,21 +206,11 @@   ceiling = P.ceiling   floor = P.floor -type CanRoundX t =-  (CanRound t,-   CanNegSameType t,-   CanTestPosNeg t,-   HasOrderCertainly t Integer,-   CanTestFinite t,-   Show t, Arbitrary t)- {-|   HSpec properties that each implementation of CanRound should satisfy.  -} specCanRound ::-  (CanRoundX t, HasIntegers t)-  =>-  T t -> Spec+  _ => T t -> Spec specCanRound (T typeName :: T t) =   describe (printf "CanRound %s" typeName) $ do     it "holds floor x <= x <= ceiling x" $ do@@ -239,7 +224,8 @@     it "0 <= ceiling x - floor x <= 1" $ do       property $ \ (x :: t) ->         isFinite x ==>-          (ceiling x - floor x) `elem_PF` [0,1]+          let diffCeilingFloorX = ceiling x - floor x in+          (0 ?<=? diffCeilingFloorX) .&&. (diffCeilingFloorX ?<=? 1)     it "holds floor x = round x = ceiling x for integers" $ do       property $ \ (xi :: Integer) ->         let x = convertExactly xi :: t in@@ -251,12 +237,11 @@   (!<=!$) = printArgsIfFails2 "!<=!" (!<=!)   (!==!$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property   (!==!$) = printArgsIfFails2 "!==!" (!==!)-  elem_PF = printArgsIfFails2 "elem" elem   class HasIntegerBounds t where   integerBounds :: t -> (Integer, Integer)-  default integerBounds :: (CanRound t) => t -> (Integer, Integer)+  default integerBounds :: (CanRound t, RoundType t ~ Integer) => t -> (Integer, Integer)   integerBounds x = (floor x, ceiling x)  instance HasIntegerBounds Rational@@ -266,22 +251,11 @@ instance HasIntegerBounds Int where   integerBounds n = (n',n') where n' = integer n -type HasIntegerBoundsX t =-  (HasIntegerBounds t,-  --  CanNegSameType t,-  --  CanTestPosNeg t,-   HasOrderCertainly t Integer,-   CanTestFinite t,-   Show t, Arbitrary t)-- {-|   HSpec properties that each implementation of CanRound should satisfy.  -} specHasIntegerBounds ::-  (HasIntegerBoundsX t)-  =>-  T t -> Spec+  _ => T t -> Spec specHasIntegerBounds (T typeName :: T t) =   describe (printf "HasIntegerBounds %s" typeName) $ do     it "holds l <= x <= r" $ do
src/Utils/Test/EnforceRange.hs view
@@ -30,7 +30,7 @@ import Numeric.MixedTypes.Round  type CanEnforceRange t b =-    (CanAddSubMulDivCNBy t Integer+    (CanAddSubMulDivBy t Integer     , CanAddSameType t, CanSubSameType t, CanAbsSameType t     , CanDivIModIntegerSameType t     , ConvertibleExactly b t@@ -48,11 +48,11 @@     | not (l !<! u) = error "enforceRange: inconsistent range"     | l !<! a && a !<! u = a     | l !<! b && b !<! u = b-    | otherwise = (u-l)/!2+    | otherwise = (u+l)/2     where     l = convertExactly l_ :: t     u = convertExactly u_ :: t-    b = l + ((abs a) `modNoCN` (u-l))+    b = l + ((abs a) `mod` (u-l)) enforceRange (Just l_, _) (a::t)     | l !<! a = a     | otherwise = (2*l-a+1)
test/Numeric/MixedTypes/RoundSpec.hs view
@@ -17,7 +17,7 @@  spec :: Spec spec = do-  specCanDivIMod tInteger-  specCanDivIMod tRational+  specCanDivIMod tCNInteger+  specCanDivIMod tCNRational   specCanRound tRational   -- specCanRound tDouble