-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | numerical spaces -- -- Spaces as higher-kinded numbers. @package numhask-space @version 0.2.0 module NumHask.Space.Types class Space s where { -- | the underlying element in the space type family Element s :: *; } -- | lower boundary lower :: Space s => s -> Element s -- | upper boundary upper :: Space s => s -> Element s -- | space containing a single element singleton :: Space s => Element s -> s -- | the intersection of two spaces intersection :: Space s => s -> s -> s -- | the intersection of two spaces intersection :: (Space s, Ord (Element s)) => s -> s -> s -- | the union of two spaces union :: Space s => s -> s -> s -- | the union of two spaces union :: (Space s, Ord (Element s)) => s -> s -> s -- | Normalise a space so that > lower a / upper a == lower a > lower -- a / upper a == upper a norm :: Space s => s -> s -- | create a normalised space from two elements (...) :: Space s => Element s -> Element s -> s -- | create a normalised space from two elements (...) :: (Space s, Ord (Element s)) => Element s -> Element s -> s -- | create a space from two elements without normalising (>.<) :: Space s => Element s -> Element s -> s -- | is an element in the space (|.|) :: Space s => Element s -> s -> Bool -- | is an element in the space (|.|) :: (Space s, Ord (Element s)) => Element s -> s -> Bool -- | is one space completely above the other (|>|) :: Space s => s -> s -> Bool -- | is one space completely above the other (|>|) :: (Space s, Ord (Element s)) => s -> s -> Bool -- | is one space completely below the other (|<|) :: Space s => s -> s -> Bool -- | is one space completely below the other (|<|) :: (Space s, Ord (Element s)) => s -> s -> Bool infix 3 >.< infix 3 ... infixl 7 |.| infixl 7 |>| infixl 7 |<| newtype Union a Union :: a -> Union a [getUnion] :: Union a -> a newtype Intersection a Intersection :: a -> Intersection a [getIntersection] :: Intersection a -> a -- | a space that can be divided neatly class (Space s, Num (Element s)) => FieldSpace s where { type family Grid s :: *; } -- | create equally-spaced elements across a space grid :: FieldSpace s => Pos -> s -> Grid s -> [Element s] -- | create equally-spaced spaces from a space gridSpace :: FieldSpace s => s -> Grid s -> [s] -- | mid-point of the space mid :: (Space s, Fractional (Element s)) => s -> Element s -- | project a data point from one space to another, preserving relative -- position -- --
-- project o n (lower o) = lower n -- project o n (upper o) = upper n -- project a a x = x -- project mempty one zero = NaN -- project one mempty zero = Infinity -- project one mempty one = NaN --project :: (Space s, Fractional (Element s)) => s -> s -> Element s -> Element s -- | Pos suggests where points should be placed in forming a grid across a -- field space. data Pos OuterPos :: Pos InnerPos :: Pos LowerPos :: Pos UpperPos :: Pos MidPos :: Pos -- | the containing space of a non-empty Traversable space1 :: (Space s, Traversable f) => f (Element s) -> s memberOf :: Space s => Element s -> s -> Bool -- | is a space contained within another? contains :: Space s => s -> s -> Bool -- | are two spaces disjoint? disjoint :: Space s => s -> s -> Bool -- | distance between boundaries width :: (Space s, Num (Element s)) => s -> Element s -- | create a space centered on a plus or minus b (+/-) :: (Space s, Num (Element s)) => Element s -> Element s -> s infixl 6 +/- -- | lift a monotone function (increasing or decreasing) over a given space monotone :: (Space a, Space b) => (Element a -> Element b) -> a -> b -- | a small space eps :: (Space s, Fractional (Element s)) => Element s -> Element s -> s -- | widen a space widen :: (Space s, Num (Element s)) => Element s -> s -> s -- | widen by a small amount widenEps :: (Space s, Fractional (Element s)) => Element s -> s -> s -- | scale a Space scale :: (Num (Element s), Space s) => Element s -> s -> s -- | move a Space move :: (Num (Element s), Space s) => Element s -> s -> s instance GHC.Classes.Eq NumHask.Space.Types.Pos instance GHC.Show.Show NumHask.Space.Types.Pos instance NumHask.Space.Types.Space a => GHC.Base.Semigroup (NumHask.Space.Types.Intersection a) instance NumHask.Space.Types.Space a => GHC.Base.Semigroup (NumHask.Space.Types.Union a) -- | An Space with no empty, a semigroup based on a convex hull union, and -- a monoid on a negative space. module NumHask.Range -- | A continuous range over type a -- --
-- >>> let a = Range (-1) 1 -- -- >>> a -- Range -1 1 -- -- >>> fmap (+1) (Range 1 2) -- Range 2 3 -- -- >>> one :: Range Double -- Range -0.5 0.5 -- -- >>> zero :: Range Double -- Range Infinity -Infinity ---- -- as a Field instance -- --
-- >>> Range 0 1 + zero -- Range 0.0 1.0 -- -- >>> Range 0 1 + Range 2 3 -- Range 0.0 3.0 -- -- >>> Range 1 1 - one -- Range 0.5 1.0 -- -- >>> Range 0 1 * one -- Range 0.0 1.0 -- -- >>> Range 0 1 / one -- Range 0.0 1.0 -- -- >>> abs (Range 1 0) -- Range 0.0 1.0 -- -- >>> sign (Range 1 0) == negate one -- True ---- -- Idempotent -- --
-- >>> Range 0 2 + Range 0 2 -- Range 0.0 2.0 ---- -- as a space instance -- --
-- >>> NumHask.Space.project (Range 0 1) (Range 1 4) 0.5 -- 2.5 -- -- >>> NumHask.Space.grid NumHask.Space.OuterPos (Range 0 10) 5 -- [0.0,2.0,4.0,6.0,8.0,10.0] -- -- >>> NumHask.Space.gridSpace (Range 0 1) 4 -- [Range 0.0 0.25,Range 0.25 0.5,Range 0.5 0.75,Range 0.75 1.0] -- -- >>> gridSensible NumHask.Space.OuterPos (Range (-12.0) 23.0) 6 -- [-10.0,-5.0,0.0,5.0,10.0,15.0,20.0] --newtype Range a Range' :: (a, a) -> Range a -- | A tuple is the preferred concrete implementation of a Range, due to -- many libraries having substantial optimizations for tuples already (eg -- Vector). 'Pattern Synonyms' allow us to recover a constructor -- without the need for tuple syntax. pattern Range :: a -> a -> Range a gridSensible :: (Ord a, RealFrac a, Floating a, Integral b) => Pos -> Bool -> Range a -> b -> [a] instance GHC.Generics.Generic (NumHask.Range.Range a) instance GHC.Classes.Eq a => GHC.Classes.Eq (NumHask.Range.Range a) instance GHC.Show.Show a => GHC.Show.Show (NumHask.Range.Range a) instance Data.Functor.Classes.Eq1 NumHask.Range.Range instance Data.Functor.Classes.Show1 NumHask.Range.Range instance GHC.Base.Functor NumHask.Range.Range instance Data.Functor.Bind.Class.Apply NumHask.Range.Range instance GHC.Base.Applicative NumHask.Range.Range instance Data.Foldable.Foldable NumHask.Range.Range instance Data.Semigroup.Foldable.Class.Foldable1 NumHask.Range.Range instance Data.Traversable.Traversable NumHask.Range.Range instance Data.Semigroup.Traversable.Class.Traversable1 NumHask.Range.Range instance Data.Distributive.Distributive NumHask.Range.Range instance Data.Functor.Rep.Representable NumHask.Range.Range instance GHC.Classes.Ord a => Algebra.Lattice.Lattice (NumHask.Range.Range a) instance (GHC.Classes.Eq a, GHC.Classes.Ord a) => NumHask.Space.Types.Space (NumHask.Range.Range a) instance (GHC.Classes.Ord a, GHC.Real.Fractional a) => NumHask.Space.Types.FieldSpace (NumHask.Range.Range a) instance (GHC.Classes.Eq a, GHC.Classes.Ord a) => GHC.Base.Semigroup (NumHask.Range.Range a) instance (GHC.Num.Num a, GHC.Classes.Eq a, GHC.Classes.Ord a) => GHC.Num.Num (NumHask.Range.Range a) -- | A 2-dimensional point. module NumHask.Point -- | A 2-dim point of a's, implemented as a tuple, but api represented as -- Point a a. -- --
-- >>> fmap (+1) (Point 1 2) -- Point 2 3 -- -- >>> pure one :: Point Int -- Point 1 1 -- -- >>> (*) <$> Point 1 2 <*> pure 2 -- Point 2 4 -- -- >>> foldr (++) [] (Point [1,2] [3]) -- [1,2,3] -- -- >>> Point "a" "pair" `mappend` pure " " `mappend` Point "string" "mappended" -- Point "a string" "pair mappended" ---- -- As a Ring and Field class -- --
-- >>> Point 0 1 + zero -- Point 0 1 -- -- >>> Point 0 1 + Point 2 3 -- Point 2 4 -- -- >>> Point 1 1 - one -- Point 0 0 -- -- >>> Point 0 1 * one -- Point 0 1 -- -- >>> Point 0.0 1.0 / one -- Point 0.0 1.0 -- -- >>> Point 11 12 `mod` (pure 6) -- Point 5 0 --newtype Point a Point' :: (a, a) -> Point a -- | the preferred pattern pattern Point :: a -> a -> Point a -- | rotate a point by x degrees relative to the origin rotate :: Floating a => a -> Point a -> Point a -- | Create Points for a formulae y = f(x) across an x range gridP :: (Ord a, Fractional a) => (a -> a) -> Range a -> Int -> [Point a] instance GHC.Generics.Generic (NumHask.Point.Point a) instance GHC.Classes.Eq a => GHC.Classes.Eq (NumHask.Point.Point a) instance GHC.Show.Show a => GHC.Show.Show (NumHask.Point.Point a) instance GHC.Base.Functor NumHask.Point.Point instance Data.Functor.Classes.Eq1 NumHask.Point.Point instance Data.Functor.Classes.Show1 NumHask.Point.Point instance GHC.Base.Applicative NumHask.Point.Point instance GHC.Base.Monad NumHask.Point.Point instance Data.Foldable.Foldable NumHask.Point.Point instance Data.Traversable.Traversable NumHask.Point.Point instance GHC.Base.Semigroup a => GHC.Base.Semigroup (NumHask.Point.Point a) instance (GHC.Base.Semigroup a, GHC.Base.Monoid a) => GHC.Base.Monoid (NumHask.Point.Point a) instance GHC.Enum.Bounded a => GHC.Enum.Bounded (NumHask.Point.Point a) instance GHC.Num.Num a => GHC.Num.Num (NumHask.Point.Point a) instance GHC.Real.Fractional a => GHC.Real.Fractional (NumHask.Point.Point a) instance Data.Distributive.Distributive NumHask.Point.Point instance Data.Functor.Rep.Representable NumHask.Point.Point instance GHC.Classes.Ord a => Algebra.Lattice.Lattice (NumHask.Point.Point a) -- | a two-dimensional plane, implemented as a composite of a Point -- of Ranges. module NumHask.Rect -- | a Point of Ranges that form a rectangle in what is often -- thought of as the XY plane. -- --
-- >>> let a = Rect (-1) 1 (-2) 4 -- -- >>> a -- Rect -1 1 -2 4 -- -- >>> let (Ranges x y) = a -- -- >>> x -- Range -1 1 -- -- >>> y -- Range -2 4 -- -- >>> fmap (+1) (Rect 1 2 3 4) -- Rect 2 3 4 5 -- -- >>> one :: Rect Double -- Rect -0.5 0.5 -0.5 0.5 -- -- >>> zero :: Rect Double -- Rect Infinity -Infinity Infinity -Infinity ---- -- as a Field instance -- --
-- >>> Rect 0 1 2 3 + zero -- Rect 0.0 1.0 2.0 3.0 -- -- >>> Rect 0 1 (-2) (-1) + Rect 2 3 (-5) 3 -- Rect 0.0 3.0 -5.0 3.0 -- -- >>> Rect 1 1 1 1 - one -- Rect 0.5 1.0 0.5 1.0 -- -- >>> Rect 0 1 0 1 * one -- Rect 0.0 1.0 0.0 1.0 -- -- >>> Rect 0 1 0 1 / one -- Rect 0.0 1.0 0.0 1.0 -- -- >>> singleton (Point 1.0 2.0) :: Rect Double -- Rect 1.0 1.0 2.0 2.0 -- -- >>> abs (Rect 1 0 1 0) -- Rect 0.0 1.0 0.0 1.0 -- -- >>> sign (Rect 1 0 1 0) == negate one -- True ---- -- as a Space instance -- --
-- >>> project (Rect 0 1 (-1) 0) (Rect 1 4 10 0) (Point 0.5 1) -- Point 2.5 -10.0 -- -- >>> gridSpace (Rect 0 10 0 1) (Point 2 2) -- [Rect 0.0 5.0 0.0 0.5,Rect 0.0 5.0 0.5 1.0,Rect 5.0 10.0 0.0 0.5,Rect 5.0 10.0 0.5 1.0] -- -- >>> grid MidPos (Rect 0 10 0 1) (Point 2 2) -- [Point 2.5 0.25,Point 2.5 0.75,Point 7.5 0.25,Point 7.5 0.75] --newtype Rect a Rect' :: Compose Point Range a -> Rect a -- | pattern of Rect lowerx upperx lowery uppery pattern Rect :: a -> a -> a -> a -> Rect a -- | pattern of Ranges xrange yrange pattern Ranges :: Range a -> Range a -> Rect a -- | create a list of points representing the lower left and upper right -- corners of a rectangle. corners :: Ord a => Rect a -> [Point a] -- | the 4 corners corners4 :: Rect a -> NonEmpty (Point a) -- | project a Rect from an old range to a new 1 projectRect :: (Ord a, Fractional a) => Rect a -> Rect a -> Rect a -> Rect a -- | Rect projection maths: some sort of affine projection lurking under -- the hood? > width one = one > mid zero = zero addRect :: Num a => Rect a -> Rect a -> Rect a multRect :: (Ord a, Fractional a) => Rect a -> Rect a -> Rect a unitRect :: Fractional a => Rect a foldRect :: Ord a => [Rect a] -> Maybe (Rect a) addPoint :: Num a => Point a -> Rect a -> Rect a -- | rotate the corners of a Rect by x degrees relative to the origin, and -- fold to a new Rcet rotateRect :: (Floating a, Ord a) => a -> Rect a -> Rect a -- | Create Rects for a formulae y = f(x) across an x range gridR :: (Ord a, Fractional a) => (a -> a) -> Range a -> Int -> [Rect a] -- | Create values c for Rects data for a formulae c = f(x,y) gridF :: (Ord a, Fractional a) => (Point a -> b) -> Rect a -> Grid (Rect a) -> [(Rect a, b)] -- | convert a ratio of x-plane : y-plane to a ViewBox with a height of -- one. aspect :: Fractional a => a -> Rect a -- | convert a Rect to a ratio ratio :: Fractional a => Rect a -> a instance GHC.Generics.Generic (NumHask.Rect.Rect a) instance Data.Traversable.Traversable NumHask.Rect.Rect instance Data.Foldable.Foldable NumHask.Rect.Rect instance GHC.Base.Applicative NumHask.Rect.Rect instance GHC.Base.Functor NumHask.Rect.Rect instance GHC.Classes.Eq a => GHC.Classes.Eq (NumHask.Rect.Rect a) instance GHC.Show.Show a => GHC.Show.Show (NumHask.Rect.Rect a) instance Data.Distributive.Distributive NumHask.Rect.Rect instance Data.Functor.Rep.Representable NumHask.Rect.Rect instance GHC.Classes.Ord a => GHC.Base.Semigroup (NumHask.Rect.Rect a) instance GHC.Classes.Ord a => NumHask.Space.Types.Space (NumHask.Rect.Rect a) instance (GHC.Classes.Ord a, GHC.Real.Fractional a, GHC.Num.Num a) => NumHask.Space.Types.FieldSpace (NumHask.Rect.Rect a) -- | a continuous set of numbers mathematics does not define a space, so -- library devs are free to experiment. -- https://en.wikipedia.org/wiki/Interval_(mathematics) module NumHask.Space -- | data algorithms related to time (as a Space) module NumHask.Space.Time -- | parse text as per iso8601 -- --
-- >>> :set -XOverloadedStrings
--
-- >>> let t0 = parseUTCTime ("2017-12-05" :: Text)
--
-- >>> t0
-- Just 2017-12-05 00:00:00 UTC
--
parseUTCTime :: Text -> Maybe UTCTime
-- | a step in time
data TimeGrain
Years :: Integer -> TimeGrain
Months :: Int -> TimeGrain
Days :: Int -> TimeGrain
Hours :: Int -> TimeGrain
Minutes :: Int -> TimeGrain
Seconds :: Double -> TimeGrain
-- | compute the floor UTCTime based on the timegrain
--
-- -- >>> floorGrain (Years 5) (UTCTime (fromGregorian 1999 1 1) 0) -- 1995-12-31 00:00:00 UTC ---- --
-- >>> floorGrain (Months 3) (UTCTime (fromGregorian 2016 12 30) 0) -- 2016-09-30 00:00:00 UTC ---- --
-- >>> floorGrain (Days 5) (UTCTime (fromGregorian 2016 12 30) 1) -- 2016-12-30 00:00:00 UTC ---- --
-- >>> floorGrain (Minutes 15) (UTCTime (fromGregorian 2016 12 30) (fromDouble' $ 15*60+1)) -- 2016-12-30 00:15:00 UTC ---- --
-- >>> floorGrain (Seconds 0.1) (UTCTime (fromGregorian 2016 12 30) 0.12) -- 2016-12-30 00:00:00.1 UTC --floorGrain :: TimeGrain -> UTCTime -> UTCTime -- | compute the ceiling UTCTime based on the timegrain -- --
-- >>> ceilingGrain (Years 5) (UTCTime (fromGregorian 1999 1 1) 0) -- 2000-12-31 00:00:00 UTC ---- --
-- >>> ceilingGrain (Months 3) (UTCTime (fromGregorian 2016 12 30) 0) -- 2016-12-31 00:00:00 UTC ---- --
-- >>> ceilingGrain (Days 5) (UTCTime (fromGregorian 2016 12 30) 1) -- 2016-12-31 00:00:00 UTC ---- --
-- >>> ceilingGrain (Minutes 15) (UTCTime (fromGregorian 2016 12 30) (fromDouble' $ 15*60+1)) -- 2016-12-30 00:30:00 UTC ---- --
-- >>> ceilingGrain (Seconds 0.1) (UTCTime (fromGregorian 2016 12 30) 0.12) -- 2016-12-30 00:00:00.2 UTC --ceilingGrain :: TimeGrain -> UTCTime -> UTCTime -- | compute a sensible TimeGrain and list of UTCTimes -- --
-- >>> sensibleTimeGrid InnerPos 2 (UTCTime (fromGregorian 2016 12 31) 0, UTCTime (fromGregorian 2017 12 31) 0) -- (Months 6,[2016-12-31 00:00:00 UTC,2017-06-30 00:00:00 UTC,2017-12-31 00:00:00 UTC]) ---- --
-- >>> sensibleTimeGrid InnerPos 2 (UTCTime (fromGregorian 2017 1 1) 0, UTCTime (fromGregorian 2017 12 30) 0) -- (Months 6,[2017-06-30 00:00:00 UTC]) ---- --
-- >>> sensibleTimeGrid UpperPos 2 (UTCTime (fromGregorian 2017 1 1) 0, UTCTime (fromGregorian 2017 12 30) 0) -- (Months 6,[2017-06-30 00:00:00 UTC,2017-12-31 00:00:00 UTC]) ---- --
-- >>> sensibleTimeGrid LowerPos 2 (UTCTime (fromGregorian 2017 1 1) 0, UTCTime (fromGregorian 2017 12 30) 0) -- (Months 6,[2016-12-31 00:00:00 UTC,2017-06-30 00:00:00 UTC]) --sensibleTimeGrid :: Pos -> Int -> (UTCTime, UTCTime) -> (TimeGrain, [UTCTime]) -- | whether to include lower and upper times data PosDiscontinuous PosInnerOnly :: PosDiscontinuous PosIncludeBoundaries :: PosDiscontinuous -- | dates attached to charts are often discontinuous, but we want to -- smooth that reality over and show a continuous range on the axis The -- assumption with getSensibleTimeGrid is that there is a list of -- discountinuous UTCTimes rather than a continuous range. Output is a -- list of index points for the original [UTCTime] and label tuples, and -- a list of unused list elements. -- --
-- >>> placedTimeLabelDiscontinuous PosIncludeBoundaries (Just "%d %b") 2 [UTCTime (fromGregorian 2017 12 6) 0, UTCTime (fromGregorian 2017 12 29) 0, UTCTime (fromGregorian 2018 1 31) 0, UTCTime (fromGregorian 2018 3 3) 0] -- ([(0,"06 Dec"),(1,"31 Dec"),(2,"28 Feb"),(3,"03 Mar")],[]) --placedTimeLabelDiscontinuous :: PosDiscontinuous -> Maybe Text -> Int -> [UTCTime] -> ([(Int, Text)], [UTCTime]) instance GHC.Generics.Generic NumHask.Space.Time.TimeGrain instance GHC.Classes.Eq NumHask.Space.Time.TimeGrain instance GHC.Show.Show NumHask.Space.Time.TimeGrain