packages feed

numhask 0.11.1.0 → 0.12.0.0

raw patch · 15 files changed

+314/−104 lines, 15 filesdep −QuickCheck

Dependencies removed: QuickCheck

Files

ChangeLog.md view
@@ -1,3 +1,23 @@+0.12+===++- added SemiField, and bumped QuotientField to default for Subtraction.++- moved infinity & nqn to SemiField, from Field.++- introduced NumHask.Data.Positive++- introduced NumHask.Data.Wrapped++- Monus & Addus++- hiding Prelude.Rational++0.11.1.0+===+* Added Sum (..)+* Added Product (..)+ 0.11.0.0 === 
numhask.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: numhask-version: 0.11.1.0+version: 0.12.0.0 license: BSD-3-Clause license-file: LICENSE copyright: Tony Day (c) 2016@@ -27,7 +27,7 @@  build-type: Simple tested-with:-    GHC ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.5 || ==9.6.2+    GHC ==9.4.8 || ==9.6.4 || ==9.8.1 extra-doc-files:     ChangeLog.md     other/*.svg@@ -46,74 +46,14 @@         -Wpartial-fields         -Wredundant-constraints -    if impl ( ghc >= 8.8 )-        ghc-options:-            -fwrite-ide-info-            -hiedir=.hie- common ghc2021-stanza-    if impl ( ghc >= 9.2 )-        default-language: GHC2021--    if impl ( ghc < 9.2 )-        default-language: Haskell2010-        default-extensions:-            BangPatterns-            BinaryLiterals-            ConstrainedClassMethods-            ConstraintKinds-            DeriveDataTypeable-            DeriveFoldable-            DeriveFunctor-            DeriveGeneric-            DeriveLift-            DeriveTraversable-            DoAndIfThenElse-            EmptyCase-            EmptyDataDecls-            EmptyDataDeriving-            ExistentialQuantification-            ExplicitForAll-            FlexibleContexts-            FlexibleInstances-            ForeignFunctionInterface-            GADTSyntax-            GeneralisedNewtypeDeriving-            HexFloatLiterals-            ImplicitPrelude-            InstanceSigs-            KindSignatures-            MonomorphismRestriction-            MultiParamTypeClasses-            NamedFieldPuns-            NamedWildCards-            NumericUnderscores-            PatternGuards-            PolyKinds-            PostfixOperators-            RankNTypes-            RelaxedPolyRec-            ScopedTypeVariables-            StandaloneDeriving-            StarIsType-            TraditionalRecordSyntax-            TupleSections-            TypeApplications-            TypeOperators-            TypeSynonymInstances--    if impl ( ghc < 9.2 ) && impl ( ghc >= 8.10 )-        default-extensions:-            ImportQualifiedPost-            StandaloneKindSignatures+    default-language: GHC2021  library     import: ghc-options-stanza     import: ghc2021-stanza     hs-source-dirs: src     build-depends:-        -- keeping cabal-docspec happy-        , QuickCheck >=2.14 && <3         , base       >=4.7 && <5     exposed-modules:         NumHask@@ -127,12 +67,9 @@         NumHask.Algebra.Ring         NumHask.Data.Complex         NumHask.Data.Integral+        NumHask.Data.Positive         NumHask.Data.Rational+        NumHask.Data.Wrapped         NumHask.Exception         NumHask.Prelude-    other-modules:     default-extensions: RebindableSyntax--    -- keeping ormolu happy-    if impl ( ghc >= 8.10 )-        default-extensions: NoImportQualifiedPost
src/NumHask/Algebra/Additive.hs view
@@ -14,7 +14,7 @@ import Data.Word (Word, Word16, Word32, Word64, Word8) import GHC.Natural (Natural (..)) import Prelude (Bool, Double, Eq, Float, Int, Integer, Ord, Show, fromInteger)-import qualified Prelude as P+import Prelude qualified as P  -- $setup --@@ -44,6 +44,8 @@   zero :: a  -- | A wrapper for an Additive which distinguishes the additive structure+--+-- @since 0.11.1 newtype Sum a = Sum   { getSum :: a   }
src/NumHask/Algebra/Field.hs view
@@ -3,7 +3,8 @@  -- | Field classes module NumHask.Algebra.Field-  ( Field,+  ( SemiField,+    Field,     ExpField (..),     QuotientField (..),     infinity,@@ -25,7 +26,7 @@ import NumHask.Algebra.Ring (Distributive, Ring, two) import NumHask.Data.Integral (Integral, even) import Prelude ((.))-import qualified Prelude as P+import Prelude qualified as P  -- $setup --@@ -33,6 +34,9 @@ -- >>> :set -XScopedTypeVariables -- >>> import NumHask.Prelude +-- | A <https://en.wikipedia.org/wiki/Semifield Semifield> is a field with no substraction.+type SemiField a = (Distributive a, Divisive a)+ -- | A <https://en.wikipedia.org/wiki/Field_(mathematics) Field> is a set --   on which addition, subtraction, multiplication, and division are defined. It is also assumed that multiplication is distributive over addition. --@@ -106,7 +110,7 @@ -- See [Field of fractions](https://en.wikipedia.org/wiki/Field_of_fractions) -- -- > \a -> a - one < floor a <= a <= ceiling a < a + one-class (Field a) => QuotientField a where+class (SemiField a) => QuotientField a where   type Whole a :: Type   properFraction :: a -> (Whole a, a) @@ -119,16 +123,16 @@   --   -- >>> round (2.5 :: Double)   -- 2-  round :: (P.Eq (Whole a), Ring (Whole a)) => a -> Whole a-  default round :: (Integral (Whole a), P.Eq (Whole a), P.Ord a, Ring (Whole a)) => a -> Whole a+  round :: a -> Whole a+  default round :: (Subtractive a, Integral (Whole a), P.Eq (Whole a), P.Ord a, Subtractive (Whole a)) => a -> Whole a   round x = case properFraction x of     (n, r) ->       let m = bool (n + one) (n - one) (r P.< zero)-          half_down = abs' r - half+          half_up = abs' r + half           abs' a             | a P.< zero = negate a             | P.otherwise = a-       in case P.compare half_down zero of+       in case P.compare half_up one of             P.LT -> n             P.EQ -> bool m n (even n)             P.GT -> m@@ -137,9 +141,9 @@   --   -- >>> ceiling (1.001 :: Double)   -- 2-  ceiling :: (Distributive (Whole a)) => a -> Whole a+  ceiling :: a -> Whole a   default ceiling :: (P.Ord a, Distributive (Whole a)) => a -> Whole a-  ceiling x = bool n (n + one) (r P.>= zero)+  ceiling x = bool n (n + one) (r P.> zero)     where       (n, r) = properFraction x @@ -147,8 +151,8 @@   --   -- >>> floor (1.001 :: Double)   -- 1-  floor :: (Ring (Whole a)) => a -> Whole a-  default floor :: (P.Ord a, Ring (Whole a)) => a -> Whole a+  floor :: a -> Whole a+  default floor :: (P.Ord a, Subtractive (Whole a), Distributive (Whole a)) => a -> Whole a   floor x = bool n (n - one) (r P.< zero)     where       (n, r) = properFraction x@@ -160,8 +164,8 @@   --   -- >>> truncate (-1.001 :: Double)   -- -1-  truncate :: (Ring (Whole a)) => a -> Whole a-  default truncate :: (P.Ord a, Ring (Whole a)) => a -> Whole a+  truncate :: a -> Whole a+  default truncate :: (P.Ord a) => a -> Whole a   truncate x = bool (ceiling x) (floor x) (x P.> zero)  instance QuotientField P.Float where@@ -179,7 +183,7 @@ -- -- >>> infinity + 1 -- Infinity-infinity :: (Field a) => a+infinity :: (SemiField a) => a infinity = one / zero  -- | nan is defined as zero/zero@@ -188,7 +192,7 @@ -- -- >>> nan == zero / zero -- False-nan :: (Field a) => a+nan :: (SemiField a) => a nan = zero / zero  -- | negative infinity@@ -264,9 +268,9 @@   acosh f = acosh . f   atanh f = atanh . f --- | A 'half' is a 'Field' because it requires addition, multiplication and division.+-- | A half of 'one' -- -- >>> half :: Double -- 0.5-half :: (Field a) => a+half :: (Additive a, Divisive a) => a half = one / two
src/NumHask/Algebra/Lattice.hs view
@@ -76,17 +76,20 @@  -- | A join-semilattice with an identity element 'bottom' for '\/'. ----- > Identity: x \/ bottom == x+-- > x \/ bottom == bottom class (JoinSemiLattice a) => BoundedJoinSemiLattice a where   bottom :: a  -- | A meet-semilattice with an identity element 'top' for '/\'. ----- > Identity: x /\ top == x+-- > x /\ top == top class (MeetSemiLattice a) => BoundedMeetSemiLattice a where   top :: a  -- | Lattices with both bounds+--+-- > x /\ bottom == x+-- > x \/ top = x type BoundedLattice a = (JoinSemiLattice a, MeetSemiLattice a, BoundedJoinSemiLattice a, BoundedMeetSemiLattice a)  instance JoinSemiLattice Float where
src/NumHask/Algebra/Metric.hs view
@@ -40,7 +40,7 @@ import NumHask.Algebra.Multiplicative import NumHask.Algebra.Ring import Prelude (Double, Eq (..), Float, Functor (..), Int, Integer, Ord, Show, Word, fromRational)-import qualified Prelude as P+import Prelude qualified as P  -- $setup --@@ -49,6 +49,8 @@  -- | 'Basis' encapsulates the notion of magnitude (intuitively the quotienting of a higher-kinded number to a scalar one) and the basis on which the magnitude quotienting was performed. An instance needs to satisfy these laws: --+-- @since 0.11+-- -- > \a -> magnitude a >= zero -- > \a -> magnitude zero == zero -- > \a -> a == magnitude a *| basis a@@ -72,12 +74,18 @@   basis :: a -> Base a  -- | Basis where the domain and magnitude codomain are the same.+--+-- @since 0.11 type Absolute a = (Basis a, Mag a ~ a)  -- | Basis where the domain and basis codomain are the same.+--+-- @since 0.11 type Sign a = (Basis a, Base a ~ a)  -- | Basis where the domain, magnitude codomain and basis codomain are the same.+--+-- @since 0.11 type EndoBased a = (Basis a, Mag a ~ a, Base a ~ a)  -- | The absolute value of a number.@@ -92,6 +100,8 @@  -- | The sign of a number. --+-- @since 0.11+-- -- >>> signum (-1) -- -1 --@@ -196,6 +206,7 @@  -- | Convert between a "co-ordinated" or "higher-kinded" number and a direction. --+-- @since 0.7 -- -- > ray . angle == basis -- > magnitude (ray x) == one@@ -206,6 +217,8 @@  -- | Something that has a magnitude and a direction, with both expressed as the same type. --+-- @since 0.7+-- -- See [Polar coordinate system](https://en.wikipedia.org/wiki/Polar_coordinate_system) data Polar a = Polar {radial :: a, azimuth :: a}   deriving (Generic, Show, Eq)@@ -217,10 +230,14 @@   basis = azimuth  -- | Convert a higher-kinded number that has direction, to a 'Polar'+--+-- @since 0.7 polar :: (Dir (Base a) ~ Mag a, Basis a, Direction (Base a)) => a -> Polar (Mag a) polar x = Polar (magnitude x) (angle (basis x))  -- | Convert a Polar to a (higher-kinded) number that has a direction.+--+-- @since 0.07 coord :: (Scalar m ~ Dir m, MultiplicativeAction m, Direction m) => Polar (Scalar m) -> m coord x = radial x *| ray (azimuth x) @@ -290,6 +307,8 @@ instance Epsilon Word64  -- | Two dimensional cartesian coordinates.+--+-- @since 0.11 newtype EuclideanPair a = EuclideanPair {euclidPair :: (a, a)}   deriving stock     ( Generic,@@ -379,7 +398,7 @@         | x P.== zero P.&& y P.== zero = y -- must be after the other double zero tests         | P.otherwise = x + y -- x or y is a NaN, return a NaN (via +) -instance (Eq (Whole a), Ring (Whole a), QuotientField a) => QuotientField (EuclideanPair a) where+instance (QuotientField a, Subtractive a) => QuotientField (EuclideanPair a) where   type Whole (EuclideanPair a) = EuclideanPair (Whole a)    properFraction (EuclideanPair (x, y)) =
src/NumHask/Algebra/Multiplicative.hs view
@@ -13,7 +13,7 @@ import Data.Word (Word, Word16, Word32, Word64, Word8) import GHC.Natural (Natural (..)) import Prelude (Double, Eq, Float, Int, Integer, Ord, Show, fromInteger, fromRational)-import qualified Prelude as P+import Prelude qualified as P  -- $setup --@@ -43,6 +43,8 @@   one :: a  -- | A wrapper for an Multiplicative which distinguishes the multiplicative structure+--+-- @since 0.11.1 newtype Product a = Product   { getProduct :: a   }
src/NumHask/Algebra/Ring.hs view
@@ -15,7 +15,7 @@ import NumHask.Algebra.Additive (Additive ((+)), Subtractive) import NumHask.Algebra.Group (Idempotent) import NumHask.Algebra.Multiplicative (Multiplicative (..))-import qualified Prelude as P+import Prelude qualified as P  -- $setup --
src/NumHask/Data/Complex.hs view
@@ -105,7 +105,7 @@   adj (Complex (r, i)) = r +: negate i  -- Can't use DerivingVia due to extra Whole constraints-instance (Eq (Whole a), Ring (Whole a), QuotientField a) => QuotientField (Complex a) where+instance (Subtractive a, QuotientField a) => QuotientField (Complex a) where   type Whole (Complex a) = Complex (Whole a)    properFraction (Complex (x, y)) =
src/NumHask/Data/Integral.hs view
@@ -21,7 +21,7 @@ import NumHask.Algebra.Multiplicative import NumHask.Algebra.Ring import Prelude (Double, Float, Int, Integer, fst, snd, (.))-import qualified Prelude as P+import Prelude qualified as P  -- $setup --
+ src/NumHask/Data/Positive.hs view
@@ -0,0 +1,155 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++-- | Field classes+module NumHask.Data.Positive+  ( Positive (..),+    positive,+    maybePositive,+    positive_,+    Monus (..),+    Addus (..),+    MonusSemiField,+  )+where++import Control.Category ((>>>))+import Data.Bool (bool)+import Data.Maybe+import NumHask.Algebra.Action+import NumHask.Algebra.Additive+import NumHask.Algebra.Field+import NumHask.Algebra.Lattice+import NumHask.Algebra.Metric+import NumHask.Algebra.Multiplicative+import NumHask.Algebra.Ring+import NumHask.Data.Integral+import NumHask.Data.Rational+import NumHask.Data.Wrapped+import Prelude (Eq, Ord, Show)+import Prelude qualified as P++-- $setup+--+-- >>> :set -XRebindableSyntax+-- >>> import NumHask.Prelude+-- >>> import NumHask.Data.Positive++-- | zero is positive+--+-- >>> 1 :: Positive Int+-- UnsafePositive {unPositive = 1}+--+-- >>> positive 0 == zero+-- True+--+-- >>> positive (-1)+-- UnsafePositive {unPositive = 0}+--+-- >>> maybePositive (-1)+-- Nothing+newtype Positive a = UnsafePositive {unPositive :: a}+  deriving stock+    (Eq, Ord, Show)+  deriving+    ( Additive,+      Multiplicative,+      Divisive,+      Integral,+      FromInteger,+      FromRational,+      Basis,+      Direction,+      Epsilon,+      AdditiveAction,+      SubtractiveAction,+      MultiplicativeAction,+      DivisiveAction,+      JoinSemiLattice,+      MeetSemiLattice,+      BoundedMeetSemiLattice+    )+    via (Wrapped a)++instance (MeetSemiLattice a, Integral a) => FromIntegral (Positive a) a where+  fromIntegral a = positive a++instance (FromIntegral a b) => FromIntegral (Positive a) b where+  fromIntegral a = UnsafePositive (fromIntegral a)++instance (ToIntegral a b) => ToIntegral (Positive a) b where+  toIntegral (UnsafePositive a) = toIntegral a++instance (FromRatio a b) => FromRatio (Positive a) b where+  fromRatio a = UnsafePositive (fromRatio a)++instance (ToRatio a b) => ToRatio (Positive a) b where+  toRatio (UnsafePositive a) = toRatio a++instance (Additive a, JoinSemiLattice a) => BoundedJoinSemiLattice (Positive a) where+  bottom = UnsafePositive zero++instance QuotientField (Positive P.Double) where+  type Whole (Positive P.Double) = Positive P.Int+  properFraction (UnsafePositive a) = (\(n, r) -> (UnsafePositive n, UnsafePositive r)) (P.properFraction a)+  ceiling = properFraction >>> P.fst >>> (+ one)+  floor = properFraction >>> P.fst+  truncate = floor+  round x = case properFraction x of+    (n, r) ->+      let half_up = r + half+       in case P.compare half_up one of+            P.LT -> n+            P.EQ -> bool (n + one) n (even n)+            P.GT -> n + one++-- | Constructor which returns zero for a negative input.+--+-- >>> positive (-1)+-- UnsafePositive {unPositive = 0}+positive :: (Additive a, MeetSemiLattice a) => a -> Positive a+positive a = UnsafePositive (a /\ zero)++-- | Unsafe constructors.+--+-- >>> positive_ (-one)+-- UnsafePositive {unPositive = -1}+positive_ :: a -> Positive a+positive_ = UnsafePositive++-- | Constructor which returns Nothing for a negative number.+-- >>> maybePositive (-one)+-- Nothing+maybePositive :: (Additive a, MeetSemiLattice a) => a -> Maybe (Positive a)+maybePositive a = bool Nothing (Just (UnsafePositive a)) (a `meetLeq` zero)++instance (Subtractive a, MeetSemiLattice a) => Monus (Positive a) where+  (UnsafePositive a) ∸ (UnsafePositive b) = positive (a - b)++-- | A field but with truncated subtraction.+type MonusSemiField a = (Monus a, Distributive a, Divisive a)++-- | <https://en.wikipedia.org/wiki/Monus Monus> or truncated subtraction.+--+-- >>> positive 4 ∸ positive 7+-- UnsafePositive {unPositive = 0}+--+-- >>> 4 ∸ 7 :: Positive Int+-- UnsafePositive {unPositive = 0}+class Monus a where+  {-# MINIMAL (∸) #-}++  infixl 6 ∸+  (∸) :: a -> a -> a+  default (∸) :: (BoundedJoinSemiLattice a, MeetSemiLattice a, Subtractive a) => a -> a -> a+  a ∸ b = bottom /\ (a - b)++-- | Truncated addition+class Addus a where+  {-# MINIMAL (∔) #-}+  infixl 6 ∔+  (∔) :: a -> a -> a+  default (∔) :: (BoundedMeetSemiLattice a, JoinSemiLattice a, Additive a) => a -> a -> a+  a ∔ b = top \/ (a + b)
src/NumHask/Data/Rational.hs view
@@ -18,7 +18,7 @@ import Data.Word (Word, Word16, Word32, Word64, Word8) import GHC.Float import GHC.Natural (Natural (..))-import qualified GHC.Real+import GHC.Real qualified import NumHask.Algebra.Additive import NumHask.Algebra.Field import NumHask.Algebra.Lattice@@ -26,17 +26,20 @@ import NumHask.Algebra.Multiplicative import NumHask.Algebra.Ring import NumHask.Data.Integral-import Prelude (Eq (..), Int, Integer, Ord (..), Ordering (..), Rational, (.))-import qualified Prelude as P+import Prelude (Eq (..), Int, Integer, Ord (..), Ordering (..), (.))+import Prelude qualified as P  -- $setup -- -- >>> :set -XRebindableSyntax -- >>> import NumHask.Prelude --- | A rational number+-- | A rational number, represented as the ratio of two 'Integral' numbers. data Ratio a = !a :% !a deriving (P.Show) +-- | Ratio of two integers+type Rational = Ratio Integer+ instance (P.Eq a, Subtractive a, EndoBased a, Absolute a, Integral a) => P.Eq (Ratio a) where   a@(xa :% ya) == b@(xb :% yb)     | isRNaN a P.|| isRNaN b = P.False@@ -119,9 +122,6 @@ instance ToRatio Float Integer where   toRatio = fromBaseRational . P.toRational -instance ToRatio Rational Integer where-  toRatio = fromBaseRational- instance ToRatio (Ratio Integer) Integer where   toRatio = P.id @@ -178,7 +178,7 @@   fromRatio (n :% d) = rationalToFloat n d  instance FromRatio Rational Integer where-  fromRatio (n :% d) = n GHC.Real.% d+  fromRatio = P.id  -- | fromRational is special in two ways: --
+ src/NumHask/Data/Wrapped.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++-- | Wrapped numhask instances, useful for derivingvia situations to quickly specifiy a numhask friendly numerical type.+module NumHask.Data.Wrapped+  ( Wrapped (..),+  )+where++import NumHask.Algebra.Action+import NumHask.Algebra.Additive+import NumHask.Algebra.Field+import NumHask.Algebra.Lattice+import NumHask.Algebra.Metric+import NumHask.Algebra.Multiplicative+import NumHask.Algebra.Ring+import NumHask.Data.Integral+import NumHask.Data.Rational+import Prelude qualified as P++-- | Wrapped numhask instances+newtype Wrapped a = Wrapped {unWrapped :: a}+  deriving+    ( P.Show,+      P.Eq,+      P.Ord,+      Additive,+      Subtractive,+      Multiplicative,+      Divisive,+      ExpField,+      TrigField,+      StarSemiring,+      InvolutiveRing,+      Integral,+      FromInteger,+      FromRational,+      MeetSemiLattice,+      JoinSemiLattice,+      BoundedJoinSemiLattice,+      BoundedMeetSemiLattice,+      Basis,+      Direction,+      Epsilon,+      AdditiveAction,+      SubtractiveAction,+      MultiplicativeAction,+      DivisiveAction+    )++instance+  (P.Ord a, P.Eq (Whole a), Integral (Whole a), Subtractive (Whole a), Subtractive a, QuotientField a) =>+  QuotientField (Wrapped a)+  where+  type Whole (Wrapped a) = Whole a+  properFraction (Wrapped a) = let (i, r) = properFraction a in (i, Wrapped r)++instance (FromIntegral a b) => FromIntegral (Wrapped a) b where+  fromIntegral a = Wrapped (fromIntegral a)++instance (ToIntegral a b) => ToIntegral (Wrapped a) b where+  toIntegral (Wrapped a) = toIntegral a++instance (FromRatio a b) => FromRatio (Wrapped a) b where+  fromRatio a = Wrapped (fromRatio a)++instance (ToRatio a b) => ToRatio (Wrapped a) b where+  toRatio (Wrapped a) = toRatio a
src/NumHask/Exception.hs view
@@ -7,7 +7,7 @@  import Control.Exception import Data.Typeable (Typeable)-import qualified Prelude as P+import Prelude qualified as P  -- | A numhask exception. newtype NumHaskException = NumHaskException {errorMessage :: P.String}
src/NumHask/Prelude.hs view
@@ -75,7 +75,7 @@ import NumHask.Data.Integral import NumHask.Data.Rational import NumHask.Exception-import Prelude hiding (Integral (..), abs, acos, acosh, asin, asinh, atan, atan2, atanh, ceiling, cos, cosh, even, exp, floor, fromInteger, fromIntegral, fromRational, gcd, id, log, logBase, negate, odd, pi, product, properFraction, recip, round, signum, sin, sinh, sqrt, subtract, sum, tan, tanh, toInteger, toRational, truncate, (*), (**), (+), (-), (.), (/), (^), (^^))+import Prelude hiding (Integral (..), Rational, abs, acos, acosh, asin, asinh, atan, atan2, atanh, ceiling, cos, cosh, even, exp, floor, fromInteger, fromIntegral, fromRational, gcd, id, log, logBase, negate, odd, pi, product, properFraction, recip, round, signum, sin, sinh, sqrt, subtract, sum, tan, tanh, toInteger, toRational, truncate, (*), (**), (+), (-), (.), (/), (^), (^^))  -- $usage --