-- | Class instances for the continued fraction datatype {-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-} module Data.Number.Instances where import Data.Number.Types import Data.Number.Internal -- | transform a number applying a function ('Nat' -> 'Nat') to each -- number preserving the sign. instance Functor Continued where fmap _ E = E fmap f (M x) = M (fmap f x) fmap f (x:|xs) = f x :| fmap f xs -- | Basic Foldable instance implemented exactly as a list. instance Foldable Continued where foldr f z E = z foldr f z (M x) = foldr f z x foldr f z (x:|xs) = f x (foldr f z xs) -- | Same as above. instance Traversable Continued where traverse _ E = pure E traverse f (M x) = traverse f x traverse f (x:|xs) = (:|) <$> f x <*> traverse f xs -- | The sign is given by the first number of the fraction. -- Other number are always considered positive. instance Num Number where (+) = biHom (0, 1, 1, 0, 1, 0, 0, 0) (-) = biHom (0, 1, -1, 0, 1, 0, 0, 0) (*) = biHom (0, 0, 0, 1, 1, 0, 0, 0) abs (M x) = x abs x = x negate (M x) = x negate x = M x fromInteger = toNumber . fromIntegral signum E = 0 signum (M _) = -1 signum _ = 1 -- | Allows conversion to a rational instance Real Number where toRational = fromNumber -- | Allows division between 'Number's and conversion from a rational instance Fractional Number where (/) = biHom (0, 1, 0, 0, 0, 0, 1, 0) fromRational = toNumber -- Helpers -- -- | Convert a 'Number' into a 'RealFrac' number fromNumber :: RealFrac a => Number -> a fromNumber E = 0 fromNumber (M x) = negate (fromNumber x) fromNumber (x :| E) = fromIntegral x fromNumber (x :| xs) = fromIntegral x + 1 / (fromNumber xs)