{-# LANGUAGE NegativeLiterals #-} {-# LANGUAGE RebindableSyntax #-} {-# OPTIONS_GHC -Wall #-} {-# OPTIONS_HADDOCK prune #-} -- | Numeric classes. module NumHask ( -- * Usage -- $setup -- * Overview -- $overview -- $pictures -- * Prelude Mappings -- $mapping -- $backend -- * Extensions -- $extensions -- * Exports module NumHask.Algebra.Additive, module NumHask.Algebra.Field, module NumHask.Algebra.Group, module NumHask.Algebra.Lattice, module NumHask.Algebra.Module, module NumHask.Algebra.Multiplicative, module NumHask.Algebra.Ring, module NumHask.Analysis.Metric, module NumHask.Data.Complex, module NumHask.Data.Integral, module NumHask.Data.LogField, module NumHask.Data.Rational, module NumHask.Data.Positive, module NumHask.Exception, ) where import NumHask.Algebra.Additive import NumHask.Algebra.Field import NumHask.Algebra.Group import NumHask.Algebra.Lattice import NumHask.Algebra.Module import NumHask.Algebra.Multiplicative import NumHask.Algebra.Ring import NumHask.Analysis.Metric import NumHask.Data.Complex import NumHask.Data.Integral import NumHask.Data.LogField import NumHask.Data.Positive import NumHask.Data.Rational import NumHask.Exception -- $setup -- -- >>> :set -XRebindableSyntax -- >>> :set -XNegativeLiterals -- >>> import NumHask.Prelude -- >>> 1+1 -- 2 -- $extensions -- -- [RebindableSyntax](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/rebindable_syntax.html) and [NegativeLiterals](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/negative_literals.html) are both recommended for use with numhask. [LexicalNegation](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/lexical_negation.html) also looks sweet when it arrives. -- -- As a replacement for the numerical classes, numhask clashes significantly with an unqualified import of the @Prelude@. Either numhask modules should be qualified, or prelude turned off with the NoImplicitPrelude extension, or with RebindableSyntax, which implies NoImplicitPrelude. -- -- == defaulting -- -- Without RebindableSyntax, numeric literals default as follows: -- -- >>> :set -XNoRebindableSyntax -- >>> :t 1 -- 1 :: Num p => p -- -- >>> :t 1.0 -- 1.0 :: Fractional p => p -- -- With RebindableSyntax (which also switches NoImplicitPrelude on) literal numbers change to the numhask types, 'FromInteger' and 'FromRational': -- -- >>> :set -XRebindableSyntax -- >>> :t 1 -- 1 :: FromInteger a => a -- -- >>> :t 1.0 -- 1.0 :: FromRational a => a -- -- >>> 1 -- 1 -- -- >>> 1.0 -- 1.0 -- -- It is recommended to switch on RebindableSyntax to avoid Num constraints being introduced due to literal defaulting. The extension is a tradeoff, however, and usage comes attached with other non-numeric changes that "NumHask.Prelude" attempts to counteract. -- -- See See [haskell2010 Section 4.3.4](https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-750004.3) for the nuts and bolts to defaulting. -- -- The effect of [ExtendedDefaultRules](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/ghci.html#extension-ExtendedDefaultRules) in ghci or switched on as an extension also need to be understood. It can lead to unusual interactions with numerics and strange error messages at times because it adds @()@ and @[]@ to the start of the type defaulting list. -- -- == Negatives -- -- Without [NegativeLiterals](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/negative_literals.html), GHC and Haskell often reads a negative as subtraction rather than a minus. -- -- > :set -XNoNegativeLiterals -- > :t Point 1 -2 -- Point 1 -2 -- :: (Subtractive (Point a), FromInteger a, -- FromInteger (a -> Point a)) => -- a -> Pair a -- ... -- -- > :set -XNegativeLiterals -- > :t Point 1 -2 -- Point 1 -2 :: FromInteger a => Point a -- -- > Point 1 -2 -- Point 1 -2 -- -- [LexicalNegation](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/lexical_negation.html) is coming soon as a valid replacement for NegativeLiterals and will tighten things up further. -- $overview -- numhask is largely a set of classes that can replace the 'GHC.Num.Num' class and it's descendents. Principles that have guided design include: -- -- - __/balanced class density/__. The numeric heirarchy begins with addition and multiplication, choosing not to build from a 'Magma' base. Whilst not being as principled as other approaches, this circumvents the instance explosion problems of Haskell whilst maintaining clarity of class purpose. -- -- - __/operator-first/__. In most cases, a class exists to define useful operators. The exceptions are 'Distributive', 'Ring' and 'Field', which are collections of operators representing major teleological fault lines. -- -- - __/lawful/__. Most classes have laws associated with them that serve to relate class operators together in a meaningful way. -- -- - __/low-impact/__. The library attempts to fit in with the rest of the Haskell ecosystem. It provides instances for common numbers: 'GHC.Num.Int', 'GHC.Num.Integer', 'GHC.Float.Double', 'GHC.Float.Float' and the Word classes. It avoids name (or idea) clashes with other popular libraries and adopts conventions in the where they make sense. -- -- - __/proof-of-concept/__. The library may be below industrial-strength depending on a definition of this term. At the same time, correspondence around improving the library is most welcome. -- $pictures -- -- The class heirarchy looks somewhat like this: -- ![classes](other/nh.svg) -- -- If the base started with magma, and the library tolerated clashing with 'Data.Semigroup' and 'Data.Monoid' in base, it would look like: -- -- ![magma classes](other/nhmagma.svg) -- -- These first two levels, contained in 'NumHask.Algebra.Group' can be considered "morally" super-classes. -- $mapping -- -- 'GHC.Num' is a very old part of haskell, and is virtually unchanged since it's specification in [haskell98](https://www.haskell.org/onlinereport/standard-prelude.html). -- -- A deconstruction of 'GHC.Num.Num' and mapping to numhask. -- -- > -- | Basic numeric class. -- > class Num a where -- > {-# MINIMAL (+), (*), abs, signum, fromInteger, (negate | (-)) #-} -- > -- > (+), (-), (*) :: a -> a -> a -- > -- | Unary negation. -- > negate :: a -> a -- -- '(+)' is an operator of the 'Additive' class -- -- '(-)' & 'negate' are functions in the 'Subtractive' class, and -- -- '(*)' is an operator of the 'Multiplicative' class. -- -- 'zero' and 'one' are also introduced to the numeric heirarchy. -- -- > -- | Absolute value. -- > abs :: a -> a -- > -- | Sign of a number. -- > -- The functions 'abs' and 'signum' should satisfy the law: -- > -- -- > -- > abs x * signum x == x -- > -- -- > -- For real numbers, the 'signum' is either @-1@ (negative), @0@ (zero) -- > -- or @1@ (positive). -- > signum :: a -> a -- -- 'abs' is a function in the 'NumHask.Analysis.Metric.Signed' class. The concept of an absolute value can also include situations where the domain and codomain are different, and 'norm' as a function in the 'NumHask.Analysis.Metric.Norm' class is supplied for these cases. -- -- 'NumHask.Analysis.Metric.sign' replaces 'GHC.Num.signum', because signum is simply a naming crime. 'NumHask.Analysis.Metric.basis' can also be seen as a generalisation of sign. -- -- > -- | Conversion from an 'Integer'. -- > -- An integer literal represents the application of the function -- > -- 'fromInteger' to the appropriate value of type 'Integer', -- > -- so such literals have type @('Num' a) => a@. -- > fromInteger :: Integer -> a -- -- 'FromInteger' becomes its own class and 'FromIntegral' is introduced to polymorphise the covariant. -- -- Mappings from other areas of prelude include:\ -- -- 'GHC.Real.Integral' becomes 'Integral' and a polymorphic 'ToIntegral' is introduced. -- -- 'GHC.Real.Fractional' is roughly synonymous to 'Field' together with a polymorphic 'FromRatio'. -- -- 'GHC.Real.RealFrac' becomes the polymorphic 'QuotientField' -- -- 'GHC.Float.Floating' is split into 'ExpField' and 'TrigField' -- -- 'GHC.Float.RealFloat' is not attempted. Life is too short. -- $backend -- NumHask imports [protolude](https://hackage.haskell.org/package/protolude) as a base prelude with some minor tweaks.