numhask 0.3.0.0 → 0.3.1
raw patch · 13 files changed
+333/−225 lines, 13 files
Files
- numhask.cabal +2/−2
- src/NumHask/Algebra/Abstract/Field.hs +14/−36
- src/NumHask/Algebra/Abstract/Ring.hs +1/−1
- src/NumHask/Algebra/Abstract/TensorProduct.hs +13/−0
- src/NumHask/Algebra/Linear/Hadamard.hs +2/−2
- src/NumHask/Analysis/Metric.hs +1/−1
- src/NumHask/Data/Complex.hs +6/−7
- src/NumHask/Data/Integral.hs +173/−64
- src/NumHask/Data/LogField.hs +10/−47
- src/NumHask/Data/Pair.hs +4/−6
- src/NumHask/Data/Positive.hs +0/−1
- src/NumHask/Data/Rational.hs +81/−53
- src/NumHask/Data/Wrapped.hs +26/−5
numhask.cabal view
@@ -1,5 +1,5 @@ name: numhask-version: 0.3.0.0+version: 0.3.1 synopsis: numeric classes description:@@ -23,7 +23,7 @@ build-type: Simple cabal-version:- 1.18+ 2.0 extra-doc-files: other/*.svg
src/NumHask/Algebra/Abstract/Field.hs view
@@ -1,5 +1,10 @@ {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS_GHC -Wall #-} -- | Field classes@@ -20,6 +25,7 @@ import NumHask.Algebra.Abstract.Ring import NumHask.Data.Integral import qualified Prelude as P+import Prelude ((.)) -- | A <https://en.wikipedia.org/wiki/Field_(mathematics) Field> is an -- Integral domain in which every non-zero element has a multiplicative@@ -54,7 +60,7 @@ instance Field P.Float --- instance Field b => Field (a -> b)+instance Field b => Field (a -> b) -- | A hyperbolic field class --@@ -82,26 +88,21 @@ log = P.log (**) = (P.**) -{- instance ExpField b => ExpField (a -> b) where exp f = exp . f log f = log . f- logBase f f' = \a -> logBase (f a) (f' a)+ logBase f f' a = logBase (f a) (f' a) f ** f' = \a -> f a ** f' a sqrt f = sqrt . f--} --- | quotient fields explode constraints if they allow for polymorphic integral types--- -- > a - one < floor a <= a <= ceiling a < a + one -- > round a == floor (a + one/(one+one)) ----- fixme: had to redefine Signed operators here because of the Field import in Metric, itself due to Complex being defined there-class (Field a, Subtractive a, Integral b) => QuotientField a b where+class (Field a, Subtractive a, Multiplicative b, Additive b) => QuotientField a b where properFraction :: a -> (b, a) round :: a -> b- default round ::(P.Ord a, P.Ord b, Subtractive b) => a -> b+ default round ::(P.Ord a, P.Ord b, Subtractive b, Integral b) => a -> b round x = case properFraction x of (n,r) -> let m = bool (n+one) (n-one) (r P.< zero)@@ -135,10 +136,9 @@ instance QuotientField P.Double P.Integer where properFraction = P.properFraction -{- instance QuotientField b c => QuotientField (a -> b) (a -> c) where- properFraction f = (fst . frac, snd . frac)- where+ properFraction f = (P.fst . frac, P.snd . frac)+ where frac a = properFraction @b @c (f a) round f = round . f@@ -149,8 +149,6 @@ truncate f = truncate . f --}- -- | A bounded field includes the concepts of infinity and NaN, thus moving away from error throwing. -- -- > one / zero + infinity == infinity@@ -167,22 +165,14 @@ nan :: a nan = zero / zero - isNaN :: a -> P.Bool--instance UpperBoundedField P.Float where- isNaN = P.isNaN+instance UpperBoundedField P.Float -instance UpperBoundedField P.Double where- isNaN = P.isNaN+instance UpperBoundedField P.Double -{- instance UpperBoundedField b => UpperBoundedField (a -> b) where infinity _ = infinity nan _ = nan- isNaN = P.undefined --}- class (Subtractive a, Field a) => LowerBoundedField a where @@ -193,19 +183,9 @@ instance LowerBoundedField P.Double -{- instance LowerBoundedField b => LowerBoundedField (a -> b) where negInfinity _ = negInfinity --}---- | todo: work out boundings for complex--- as it stands now, complex is different eg------ > one / (zero :: Complex Float) == nan--- instance (UpperBoundedField a) =>--- UpperBoundedField (Complex a)- -- | Trigonometric Field class (Field a) => TrigField a where@@ -251,7 +231,6 @@ acosh = P.acosh atanh = P.atanh -{- instance TrigField b => TrigField (a -> b) where pi _ = pi sin f = sin . f@@ -264,7 +243,6 @@ asinh f = asinh . f acosh f = acosh . f atanh f = atanh . f--} half :: (Field a) => a half = one / two
src/NumHask/Algebra/Abstract/Ring.hs view
@@ -51,7 +51,7 @@ -- | A <https://en.wikipedia.org/wiki/Semiring Semiring> is a ring without, -- necessarily, negative elements. ----- TODO: rule zero' = zero. Is this somehow expressible in haskell?+-- FIXME: rule zero' = zero. Is this somehow expressible in haskell? class (Distributive a) => Semiring a where instance (Distributive a) =>
src/NumHask/Algebra/Abstract/TensorProduct.hs view
@@ -1,11 +1,13 @@ {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# OPTIONS_GHC -Wall #-} -- | TensorProduct module NumHask.Algebra.Abstract.TensorProduct ( TensorProduct(..)+ , TensorProduct'(..) , type (><) ) where @@ -66,3 +68,14 @@ outer = (><) timesleft :: a -> (a >< a) -> a timesright :: (a >< a) -> a -> a++-- | generalised outer product+--+-- > a><b + c><b == (a+c) >< b+-- > a><b + a><c == a >< (b+c)+-- > a *. (b><c) == (a><b) .* c+-- > (a><b) .* c == a *. (b><c)+class TensorProduct' a b where+ outer' :: a -> b -> (a >< b)+ timesleft' :: a -> (a >< b) -> b+ timesright' :: (a >< b) -> a -> b
src/NumHask/Algebra/Linear/Hadamard.hs view
@@ -20,13 +20,13 @@ -- -- > (a .*. b) .*. c == a .*. (b .*. c) -- > singleton one .*. a = a--- > a .*. singelton one = a+-- > a .*. singleton one = a -- > a .*. b == b .*. a class (Multiplicative a) => HadamardMultiplication m a where infixl 7 .*. (.*.) :: m a -> m a -> m a- (.*.) = coerce ((.*.) @m @a)+ -- (.*.) = coerce ((.*.) @m @a) -- | element by element division
src/NumHask/Analysis/Metric.hs view
@@ -273,7 +273,7 @@ epsilon = zero nearZero :: a -> Bool- nearZero a = a `meetLeq` epsilon && negate a `meetLeq` epsilon+ nearZero a = epsilon `meetLeq` a && epsilon `meetLeq` negate a aboutEqual :: a -> a -> Bool aboutEqual a b = nearZero $ a - b
src/NumHask/Data/Complex.hs view
@@ -5,6 +5,7 @@ {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude #-} {-# OPTIONS_GHC -Wall #-} module NumHask.Data.Complex where@@ -18,9 +19,8 @@ import NumHask.Algebra.Abstract.Ring import NumHask.Analysis.Metric import NumHask.Data.Integral- import Prelude- hiding (Num(..), (**), (/), atan, cos, exp, log, negate, pi, recip, sin, sqrt, isNaN)+ hiding (Num(..), (/), atan, cos, exp, log, negate, pi, recip, sin, sqrt) import qualified Prelude as P (Ord(..), (&&), (<), (<=), (==), (>), otherwise) -- -----------------------------------------------------------------------------@@ -78,9 +78,9 @@ where d = recip ((rx * rx) + (ix * ix)) -instance (Additive a, FromInteger a) =>- FromInteger (Complex a) where- fromInteger x = fromInteger x :+ zero+instance (Additive a, FromIntegral a b) =>+ FromIntegral (Complex a) b where+ fromIntegral_ x = fromIntegral_ x :+ zero instance (Multiplicative a, ExpField a, Normed a a) => Normed (Complex a) a where@@ -118,8 +118,7 @@ instance (Distributive a, Subtractive a) => InvolutiveRing (Complex a) where adj (a :+ b) = a :+ negate b -instance (UpperBoundedField a, IntegralDomain a, Subtractive a) => UpperBoundedField (Complex a) where- isNaN (a :+ b) = isNaN a || isNaN b+instance (UpperBoundedField a, IntegralDomain a, Subtractive a) => UpperBoundedField (Complex a) instance (LowerBoundedField a) => LowerBoundedField (Complex a)
src/NumHask/Data/Integral.hs view
@@ -1,9 +1,19 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -Wall #-} -- | Integral classes module NumHask.Data.Integral ( Integral(..)- , ToInteger(..)+ , ToIntegral(..)+ , ToInteger+ , toInteger+ , FromIntegral(..) , FromInteger(..) , fromIntegral , even@@ -98,100 +108,199 @@ rem f f' a = f a `mod` f' a quotRem f f' = (\a -> fst (f a `quotRem` f' a), \a -> snd (f a `quotRem` f' a)) --- | toInteger is kept separate from Integral to help with compatability issues.-class ToInteger a where- toInteger :: a -> Integer+-- | toIntegral is kept separate from Integral to help with compatability issues.+-- > toIntegral a == a+class ToIntegral a b where+ toIntegral :: a -> b+ default toIntegral :: (a ~ b) => a -> b+ toIntegral = P.id -instance ToInteger Int where- toInteger = P.toInteger+type ToInteger a = ToIntegral a Integer -instance ToInteger Integer where- toInteger = P.toInteger+-- fitting in with legacy naming conventions.+toInteger :: (ToInteger a) => a -> Integer+toInteger = toIntegral -instance ToInteger Natural where- toInteger = P.toInteger+instance ToIntegral Integer Integer where+ toIntegral = P.id -instance ToInteger Int8 where- toInteger = P.toInteger+instance ToIntegral Int Integer where+ toIntegral = P.toInteger -instance ToInteger Int16 where- toInteger = P.toInteger+instance ToIntegral Natural Integer where+ toIntegral = P.toInteger -instance ToInteger Int32 where- toInteger = P.toInteger+instance ToIntegral Int8 Integer where+ toIntegral = P.toInteger -instance ToInteger Int64 where- toInteger = P.toInteger+instance ToIntegral Int16 Integer where+ toIntegral = P.toInteger -instance ToInteger Word where- toInteger = P.toInteger+instance ToIntegral Int32 Integer where+ toIntegral = P.toInteger -instance ToInteger Word8 where- toInteger = P.toInteger+instance ToIntegral Int64 Integer where+ toIntegral = P.toInteger -instance ToInteger Word16 where- toInteger = P.toInteger+instance ToIntegral Word Integer where+ toIntegral = P.toInteger -instance ToInteger Word32 where- toInteger = P.toInteger+instance ToIntegral Word8 Integer where+ toIntegral = P.toInteger -instance ToInteger Word64 where- toInteger = P.toInteger+instance ToIntegral Word16 Integer where+ toIntegral = P.toInteger --- | fromInteger is the most problematic of the 'Num' class operators. Particularly heinous, it is assumed that any number type can be constructed from an Integer, so that the broad classes of objects that are composed of multiple elements is avoided in haskell.-class FromInteger a where- fromInteger :: Integer -> a+instance ToIntegral Word32 Integer where+ toIntegral = P.toInteger -instance FromInteger b => FromInteger (a -> b) where- fromInteger i _ = fromInteger i+instance ToIntegral Word64 Integer where+ toIntegral = P.toInteger --- | coercion of 'Integral's+instance ToIntegral Int Int where+ toIntegral = P.id++instance ToIntegral Natural Natural where+ toIntegral = P.id++instance ToIntegral Int8 Int8 where+ toIntegral = P.id++instance ToIntegral Int16 Int16 where+ toIntegral = P.id++instance ToIntegral Int32 Int32 where+ toIntegral = P.id++instance ToIntegral Int64 Int64 where+ toIntegral = P.id++instance ToIntegral Word Word where+ toIntegral = P.id++instance ToIntegral Word8 Word8 where+ toIntegral = P.id++instance ToIntegral Word16 Word16 where+ toIntegral = P.id++instance ToIntegral Word32 Word32 where+ toIntegral = P.id++instance ToIntegral Word64 Word64 where+ toIntegral = P.id++-- | fromIntegral abstracts the codomain type, compared with the preludes Integral type.+-- > fromIntegral_ a == a ----- > fromIntegral a == a-fromIntegral :: (ToInteger a, FromInteger b) => a -> b+-- fromIntegral is widely used as general coercion, hence the underscore for the operator.+class FromIntegral a b where+ fromIntegral_ :: b -> a+ default fromIntegral_ :: (a ~ b) => b -> a+ fromIntegral_ = P.id++-- | general coercion via Integer+fromIntegral :: (FromInteger b, ToInteger a) => a -> b fromIntegral = fromInteger . toInteger -instance FromInteger Double where- fromInteger = P.fromInteger+instance (FromIntegral a b) => FromIntegral (c -> a) b where+ fromIntegral_ i _ = fromIntegral_ i -instance FromInteger Float where- fromInteger = P.fromInteger+instance FromIntegral Double Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Int where- fromInteger = P.fromInteger+instance FromIntegral Float Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Integer where- fromInteger = P.fromInteger+instance FromIntegral Int Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Natural where- fromInteger = P.fromInteger+instance FromIntegral Integer Integer where+ fromIntegral_ = P.id -instance FromInteger Int8 where- fromInteger = P.fromInteger+instance FromIntegral Natural Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Int16 where- fromInteger = P.fromInteger+instance FromIntegral Int8 Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Int32 where- fromInteger = P.fromInteger+instance FromIntegral Int16 Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Int64 where- fromInteger = P.fromInteger+instance FromIntegral Int32 Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Word where- fromInteger = P.fromInteger+instance FromIntegral Int64 Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Word8 where- fromInteger = P.fromInteger+instance FromIntegral Word Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Word16 where- fromInteger = P.fromInteger+instance FromIntegral Word8 Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Word32 where- fromInteger = P.fromInteger+instance FromIntegral Word16 Integer where+ fromIntegral_ = P.fromInteger -instance FromInteger Word64 where- fromInteger = P.fromInteger+instance FromIntegral Word32 Integer where+ fromIntegral_ = P.fromInteger++instance FromIntegral Word64 Integer where+ fromIntegral_ = P.fromInteger++instance FromIntegral Int Int where+ fromIntegral_ = P.id++instance FromIntegral Natural Natural where+ fromIntegral_ = P.id++instance FromIntegral Int8 Int8 where+ fromIntegral_ = P.id++instance FromIntegral Int16 Int16 where+ fromIntegral_ = P.id++instance FromIntegral Int32 Int32 where+ fromIntegral_ = P.id++instance FromIntegral Int64 Int64 where+ fromIntegral_ = P.id++instance FromIntegral Word Word where+ fromIntegral_ = P.id++instance FromIntegral Word8 Word8 where+ fromIntegral_ = P.id++instance FromIntegral Word16 Word16 where+ fromIntegral_ = P.id++instance FromIntegral Word32 Word32 where+ fromIntegral_ = P.id++instance FromIntegral Word64 Word64 where+ fromIntegral_ = P.id++-- | ghc defaulting rules and, it seems, -XExtendedDefaultRules do not permit multiple parameter typeclasses to be in the mix when types are resolved, hence the simpler `type FromInteger a = FromIntegral a Integer` does not suffice.+class FromInteger a where+ fromInteger :: Integer -> a+ default fromInteger :: (FromIntegral a Integer) => Integer -> a+ fromInteger = fromIntegral_++instance FromInteger Integer+instance FromInteger Int+instance FromInteger Double+instance FromInteger Float+instance FromInteger Natural+instance FromInteger Int8+instance FromInteger Int16+instance FromInteger Int32+instance FromInteger Int64+instance FromInteger Word+instance FromInteger Word8+instance FromInteger Word16+instance FromInteger Word32+instance FromInteger Word64 -- $operators
src/NumHask/Data/LogField.hs view
@@ -3,6 +3,8 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wall #-} @@ -31,7 +33,7 @@ import NumHask.Analysis.Metric import NumHask.Data.Integral import NumHask.Data.Rational-import Prelude hiding (Num(..), exp, log, negate, toInteger, isNaN)+import Prelude hiding (Num(..), exp, log, negate) import qualified Data.Foldable as F -- LogField is adapted from LogFloat@@ -124,7 +126,6 @@ {-# INLINE [0] logField #-} logField = LogField . log --- TODO: figure out what to do here, removed guards -- | Constructor which assumes the argument is already in the -- log-domain. logToLogField :: a -> LogField a@@ -205,16 +206,16 @@ log (LogField x) = LogField $ log x (**) x (LogField y) = pow x $ exp y -instance (FromInteger a, ExpField a) => FromInteger (LogField a) where- fromInteger = logField . fromInteger+instance (FromIntegral a b, ExpField a) => FromIntegral (LogField a) b where+ fromIntegral_ = logField . fromIntegral_ -instance (ToInteger a, ExpField a) => ToInteger (LogField a) where- toInteger = toInteger . fromLogField+instance (ToIntegral a b, ExpField a) => ToIntegral (LogField a) b where+ toIntegral = toIntegral . fromLogField -instance (FromRatio a, ExpField a) => FromRatio (LogField a) where+instance (FromRatio a b, ExpField a) => FromRatio (LogField a) b where fromRatio = logField . fromRatio -instance (ToRatio a, ExpField a) => ToRatio (LogField a) where+instance (ToRatio a b, ExpField a) => ToRatio (LogField a) b where toRatio = toRatio . fromLogField instance (Ord a) => JoinSemiLattice (LogField a) where@@ -238,8 +239,7 @@ IntegralDomain (LogField a) where instance (Ord a, ExpField a, LowerBoundedField a, UpperBoundedField a) =>- UpperBoundedField (LogField a) where- isNaN (LogField a) = isNaN a+ UpperBoundedField (LogField a) instance (Ord a, LowerBoundedField a, UpperBoundedField a, ExpField a) => Signed (LogField a) where@@ -248,8 +248,6 @@ | otherwise = one abs = id -- ---------------------------------------------------------------- -- | /O(1)/. Compute powers in the log-domain; that is, the following -- equivalence holds (modulo underflow and all that):@@ -306,38 +304,3 @@ t' = t + y c' = (t' - t) - y in (t', c')--- This version *completely* eliminates rounding errors and loss--- of significance due to catastrophic cancellation during summation.--- <http://code.activestate.com/recipes/393090/> Also see the other--- implementations given there. For Python's actual C implementation,--- see math_fsum in--- <http://svn.python.org/view/python/trunk/Modules/mathmodule.c?view=markup>------ For merely *mitigating* errors rather than completely eliminating--- them, see <http://code.activestate.com/recipes/298339/>.------ A good test case is @msum([1, 1e100, 1, -1e100] * 10000) == 20000.0@-{---- For proof of correctness, see--- <www-2.cs.cmu.edu/afs/cs/project/quake/public/papers/robust-arithmetic.ps>-def msum(xs):- partials = [] # sorted, non-overlapping partial sums- # N.B., the actual C implementation uses a 32 array, doubling size as needed- for x in xs:- i = 0- for y in partials: # for(i = j = 0; j < n; j++)- if abs(x) < abs(y):- x, y = y, x- hi = x + y- lo = y - (hi - x)- if lo != 0.0:- partials[i] = lo- i += 1- x = hi- # does an append of x while dropping all the partials after- # i. The C version does n=i; and leaves the garbage in place- partials[i:] = [x]- # BUG: this last step isn't entirely correct and can lose- # precision <http://stackoverflow.com/a/2704565/358069>- return sum(partials, 0.0)--}
src/NumHask/Data/Pair.hs view
@@ -15,7 +15,7 @@ ) where import qualified Prelude as P-import Prelude (Foldable, Traversable, Applicative, Monad, Functor(..), Semigroup(..), Monoid(..), Bounded(..), Eq(..), (<$>), (<*>), (&&), (||))+import Prelude (Foldable, Traversable, Applicative, Monad, Functor(..), Semigroup(..), Monoid(..), Bounded(..), Eq(..), (<$>), (<*>), (&&)) import GHC.Generics (Generic) import Data.Functor.Classes import NumHask.Algebra.Abstract@@ -168,8 +168,6 @@ log = unaryOp log instance (UpperBoundedField a) => UpperBoundedField (Pair a)- where- isNaN (Pair a b) = isNaN a || isNaN b instance (LowerBoundedField a) => LowerBoundedField (Pair a) @@ -200,10 +198,10 @@ instance (BoundedMeetSemiLattice a) => BoundedMeetSemiLattice (Pair a) where top = Pair top top -instance (FromInteger a) => FromInteger (Pair a) where- fromInteger x = P.pure (fromInteger x)+instance (FromIntegral a b) => FromIntegral (Pair a) b where+ fromIntegral_ x = P.pure (fromIntegral_ x) -instance (FromRatio a) => FromRatio (Pair a) where+instance (FromRatio a b) => FromRatio (Pair a) b where fromRatio x = P.pure (fromRatio x) instance (Normed a a) =>
src/NumHask/Data/Positive.hs view
@@ -66,7 +66,6 @@ instance (UpperBoundedField a) => UpperBoundedField (Positive a) where infinity = Positive infinity- isNaN (Positive a) = isNaN a instance (UpperBoundedField a) => P.Bounded (Positive a) where minBound = zero
src/NumHask/Data/Rational.hs view
@@ -1,6 +1,11 @@ {-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wall #-} -- | Integral classes@@ -8,8 +13,13 @@ ( Ratio(..) , Rational , ToRatio(..)+ , ToRational+ , toRational , FromRatio(..)+ , FromRational , fromRational+ , fromRational'+ , fromBaseRational -- * $integral_functionality , reduce , gcd@@ -28,7 +38,7 @@ import NumHask.Algebra.Abstract.Lattice import NumHask.Analysis.Metric import NumHask.Data.Integral-import Prelude (Double, Float, Int, Integer, (.))+import Prelude (Double, Float, Int, Integer, Rational, (.)) import qualified GHC.Real import qualified Prelude as P @@ -47,10 +57,7 @@ | x P.== zero P.&& y P.== zero = P.True | P.otherwise = P.False --type Rational = Ratio Integer--instance (P.Ord a, Multiplicative a, Integral a) => P.Ord (Ratio a) where+instance (P.Ord a, Multiplicative a, Additive a) => P.Ord (Ratio a) where (x:%y) <= (x':%y') = x * y' P.<= x' * y (x:%y) < (x':%y') = x * y' P.< x' * y @@ -86,12 +93,11 @@ instance (GCDConstraints a) => Field (Ratio a) -instance (GCDConstraints a, GCDConstraints b, ToInteger a, Field a, FromInteger b) => QuotientField (Ratio a) b where- properFraction (n :% d) = let (w,r) = quotRem n d in (fromIntegral w,r:%d)+instance (GCDConstraints a, GCDConstraints b, ToInteger a, Field a, FromIntegral b a) => QuotientField (Ratio a) b where+ properFraction (n :% d) = let (w,r) = quotRem n d in (fromIntegral_ w,r:%d) instance (GCDConstraints a, Distributive a, IntegralDomain a) =>- UpperBoundedField (Ratio a) where- isNaN (a :% b) = (a P.== zero) P.&& (b P.== zero)+ UpperBoundedField (Ratio a) instance (GCDConstraints a, Field a) => LowerBoundedField (Ratio a) @@ -112,90 +118,112 @@ instance (GCDConstraints a, MeetSemiLattice a) => Epsilon (Ratio a) -instance (FromInteger a, Multiplicative a) => FromInteger (Ratio a) where- fromInteger x = fromInteger x :% one---- | toRatio is equivalent to `Real` in base.-class ToRatio a where- toRatio :: a -> Ratio Integer+instance (FromIntegral a b, Multiplicative a) => FromIntegral (Ratio a) b where+ fromIntegral_ x = fromIntegral_ x :% one -instance (ToInteger a) => ToRatio (Ratio a) where- toRatio (n :% d) = toInteger n :% toInteger d+-- | toRatio is equivalent to `Real` in base, but is polymorphic in the Integral type.+class ToRatio a b where+ toRatio :: a -> Ratio b+ default toRatio :: (Ratio c ~ a, ToIntegral c Integer, ToRatio (Ratio b) b, FromInteger b) => a -> Ratio b+ toRatio (n :% d) = toRatio ((fromIntegral n :: b) :% fromIntegral d) --- | `Fractional` in base splits into fromRatio and Field-class FromRatio a where- fromRatio :: Ratio Integer -> a+type ToRational a = ToRatio a Integer -instance (FromInteger a) => FromRatio (Ratio a) where- fromRatio (n :% d) = fromInteger n :% fromInteger d+toRational :: (ToRatio a Integer) => a -> Ratio Integer+toRational = toRatio --- | coercion of 'Rational's------ > fromRational a == a-fromRational :: (ToRatio a, FromRatio b) => a -> b-fromRational = fromRatio . toRatio+instance ToRatio Double Integer where+ toRatio = fromBaseRational . P.toRational --- | fixme: use coerce-fromBaseRational :: P.Rational -> Ratio Integer-fromBaseRational (n GHC.Real.:% d) = n :% d+instance ToRatio Float Integer where+ toRatio = fromBaseRational . P.toRational -instance FromRatio Double where- fromRatio (n:%d)= rationalToDouble n d+instance ToRatio Rational Integer where+ toRatio = fromBaseRational -instance FromRatio Float where- fromRatio (n:%d)= rationalToFloat n d+instance ToRatio (Ratio Integer) Integer where+ toRatio = P.id -instance ToRatio Double where+instance ToRatio Int Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Float where+instance ToRatio Integer Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Int where+instance ToRatio Natural Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Integer where+instance ToRatio Int8 Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Natural where+instance ToRatio Int16 Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio P.Rational where+instance ToRatio Int32 Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Int8 where+instance ToRatio Int64 Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Int16 where+instance ToRatio Word Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Int32 where+instance ToRatio Word8 Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Int64 where+instance ToRatio Word16 Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Word where+instance ToRatio Word32 Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Word8 where+instance ToRatio Word64 Integer where toRatio = fromBaseRational . P.toRational -instance ToRatio Word16 where- toRatio = fromBaseRational . P.toRational+-- | `Fractional` in base splits into fromRatio and Field+-- FIXME: work out why the default type isn't firing so that an explicit instance is needed+-- for `FromRatio (Ratio Integer) Integer`+class FromRatio a b where+ fromRatio :: Ratio b -> a+ -- default fromRatio :: (a ~ Ratio c, ToIntegral b c) => Ratio b -> a+ -- fromRatio (n :% d) = toIntegral n :% toIntegral d+ default fromRatio :: (Ratio b ~ a) => Ratio b -> a+ fromRatio = P.id -instance ToRatio Word32 where- toRatio = fromBaseRational . P.toRational+fromBaseRational :: P.Rational -> Ratio Integer+fromBaseRational (n GHC.Real.:% d) = n :% d -instance ToRatio Word64 where- toRatio = fromBaseRational . P.toRational+instance FromRatio Double Integer where+ fromRatio (n:%d)= rationalToDouble n d +instance FromRatio Float Integer where+ fromRatio (n:%d)= rationalToFloat n d++instance FromRatio Rational Integer where+ fromRatio (n:%d) = n GHC.Real.% d++instance FromRatio (Ratio Integer) Integer where+ fromRatio = P.id++-- | with RebindableSyntax the literal '1.0' mean exactly `fromRational (1.0::GHC.Real.Rational)`.+class FromRational a where+ fromRational :: P.Rational -> a+ default fromRational :: (FromRatio a Integer) => P.Rational -> a+ fromRational = fromRatio . fromBaseRational++instance FromRational Double+instance FromRational Float+instance FromRational Rational++-- | Given that fromRational is reserved, fromRational' provides general conversion between numhask rationals.+fromRational' :: (FromRatio b Integer, ToRatio a Integer) => a -> b+fromRational' a = fromRatio (toRatio a :: Ratio Integer)+ instance (GCDConstraints a) => JoinSemiLattice (Ratio a) where (\/) = P.min instance (GCDConstraints a) => MeetSemiLattice (Ratio a) where (/\) = P.max- -- * $integral_functions -- integral functionality is largely based on GHC.Real
src/NumHask/Data/Wrapped.hs view
@@ -12,6 +12,7 @@ import NumHask.Algebra.Abstract.Multiplicative import NumHask.Algebra.Abstract.Ring import NumHask.Algebra.Abstract.Lattice+import NumHask.Algebra.Abstract.Group import NumHask.Analysis.Metric import NumHask.Data.Integral import NumHask.Data.Rational@@ -22,26 +23,27 @@ ( P.Show , P.Eq , P.Ord+ , Magma+ , Idempotent , Additive , Subtractive , Multiplicative , Divisive , Distributive , IntegralDomain+ , InvolutiveRing+ , StarSemiring+ , KleeneAlgebra , Field , ExpField , TrigField , Integral , Signed- , JoinSemiLattice , MeetSemiLattice+ , JoinSemiLattice , Epsilon , UpperBoundedField , LowerBoundedField- , ToInteger- , FromInteger- , FromRatio- , ToRatio ) -- not sure if this is correct or needed@@ -51,3 +53,22 @@ QuotientField (Wrapped a) (Wrapped P.Integer) where properFraction (Wrapped a) = let (i,r) = properFraction a in (Wrapped 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++instance (Normed a b) => Normed (Wrapped a) (Wrapped b) where+ normL1 (Wrapped a) = Wrapped (normL1 a)+ normL2 (Wrapped a) = Wrapped (normL2 a)++instance (Metric a b) => Metric (Wrapped a) (Wrapped b) where+ distanceL1 (Wrapped a) (Wrapped b) = Wrapped (distanceL1 a b)+ distanceL2 (Wrapped a) (Wrapped b) = Wrapped (distanceL2 a b)