śĪ!ŽdŌ"¹      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ”¢£¤„¦§Ø©Ŗ«¬­®Æ°±²³“µ¶·øNone +8>DHVb2h& numhask-spaceRPos suggests where points should be placed in forming a grid across a field space. numhask-spaceinclude boundaries numhask-spacedon't include boundaries numhask-spaceinclude the lower boundary numhask-spaceinclude the upper boundary numhask-spaceuse the mid-point of the space numhask-space"a space that can be divided neatly Sspace1 (grid OuterPos s g) == s getUnion (sconcat (Union <$> (gridSpace s g))) == s numhask-space-create equally-spaced elements across a space  numhask-space)create equally-spaced spaces from a space  numhask-space 7https://en.wikipedia.org/wiki/Intersection_(set_theory)  numhask-space a convex hull numhask-space_Space is a continuous range of numbers that contains elements and has an upper and lower value. ’ a `union` b == b `union` a a `intersection` b == b `intersection` a (a `union` b) `intersection` c == (a `intersection` b) `union` (a `intersection` c) (a `intersection` b) `union` c == (a `union` b) `intersection` (a `union` c) norm (norm a) = norm a a |>| b == b |<| a a |.| singleton a numhask-space#the underlying element in the space numhask-spacelower boundary numhask-spaceupper boundary numhask-space!space containing a single element numhask-spacethe intersection of two spaces numhask-spacethe union of two spaces numhask-spaceNormalise a space so that ;lower a \/ upper a == lower a lower a /\ upper a == upper a numhask-space+create a normalised space from two elements numhask-space4create a space from two elements without normalising numhask-spaceis an element in the space numhask-space'is one space completely above the other numhask-space'is one space completely below the other numhask-space$is a space contained within another? 5(a `union` b) `contains` a (a `union` b) `contains` b numhask-spaceare two spaces disjoint? numhask-space&is an element contained within a space  numhask-spacedistance between boundaries! numhask-space,create a space centered on a plus or minus b" numhask-spacemiddle element of the space# numhask-spaceLproject a data point from one space to another, preserving relative position mproject o n (lower o) = lower n project o n (upper o) = upper n project o n (mid o) = mid n project a a x = x$ numhask-space/the containing space of a non-empty Traversable all $ space1 a `contains` <$> a% numhask-spaceFlift a monotone function (increasing or decreasing) over a given space& numhask-space a small space' numhask-space widen a space( numhask-spacewiden by a small amount) numhask-space&Scale a Space. (scalar multiplication)* numhask-spaceMove a Space. (scalar addition)+  !"#$%&'()*33777!6None+7@ADbj + numhask-space(whether to include lower and upper times. numhask-spacea step in time5 numhask-spaceparse text as per iso8601:set -XOverloadedStrings,let t0 = parseUTCTime ("2017-12-05" :: Text)t0Just 2017-12-05 00:00:00 UTC¹ numhask-spaceadd a TimeGrain to a UTCTime:addGrain (Years 1) 5 (UTCTime (fromGregorian 2015 2 28) 0)2020-02-29 00:00:00 UTC;addGrain (Months 1) 1 (UTCTime (fromGregorian 2015 2 28) 0)2015-03-31 00:00:00 UTC:addGrain (Hours 6) 5 (UTCTime (fromGregorian 2015 2 28) 0)2015-03-01 06:00:00 UTCJaddGrain (Seconds 0.001) (60*1000+1) (UTCTime (fromGregorian 2015 2 28) 0)2015-02-28 00:01:00.001 UTC: numhask-space0compute the floor UTCTime based on the timegrain9floorGrain (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 UTCSfloorGrain (Minutes 15) (UTCTime (fromGregorian 2016 12 30) (toDiffTime $ 15*60+1))2016-12-30 00:15:00 UTCBfloorGrain (Seconds 0.1) (UTCTime (fromGregorian 2016 12 30) 0.12)2016-12-30 00:00:00.1 UTC; numhask-space2compute 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 UTCUceilingGrain (Minutes 15) (UTCTime (fromGregorian 2016 12 30) (toDiffTime $ 15*60+1))2016-12-30 00:30:00 UTCDceilingGrain (Seconds 0.1) (UTCTime (fromGregorian 2016 12 30) 0.12)2016-12-30 00:00:00.2 UTC< numhask-space£Dates used for time series analysis or 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")],[])= numhask-space]A sensible time grid between two dates, projected onto (0,1) with no attempt to get finnicky.‹placedTimeLabelContinuous PosIncludeBoundaries (Just "%d %b") 2 (UTCTime (fromGregorian 2017 12 6) 0, UTCTime (fromGregorian 2017 12 29) 0)j[(0.0,"06 Dec"),(0.4347826086956521,"16 Dec"),(0.8695652173913042,"26 Dec"),(0.9999999999999999,"29 Dec")]> numhask-space1compute a sensible TimeGrain and list of UTCTimeshsensibleTimeGrid InnerPos 2 (UTCTime (fromGregorian 2016 12 31) 0, UTCTime (fromGregorian 2017 12 31) 0)T(Months 6,[2016-12-31 00:00:00 UTC,2017-06-30 00:00:00 UTC,2017-12-31 00:00:00 UTC])fsensibleTimeGrid InnerPos 2 (UTCTime (fromGregorian 2017 1 1) 0, UTCTime (fromGregorian 2017 12 30) 0)$(Months 6,[2017-06-30 00:00:00 UTC])fsensibleTimeGrid 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])fsensibleTimeGrid 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])ŗ numhask-space8come up with a sensible TimeGrain over a NominalDiffTime+,-./0123456789:;<=>5./01234:;>+,-<=6789None 7=?DHVbyKB numhask-spaceA continuous range over type alet a = Range (-1) 1a Range -1 1VNum instance based on interval arithmetic (with Ranges normalising to lower ... upper)a + a Range -2 2a * aRange -1.0 1.0(+1) <$> (Range 1 2) Range 2 3ŠRanges are very useful in shifting a bunch of numbers from one Range to another. eg project 0.5 from the range 0 to 1 to the range 1 to 4#project (Range 0 1) (Range 1 4) 0.52.5ACreate an equally spaced grid including outer bounds over a Range grid OuterPos (Range 0.0 10.0) 5[0.0,2.0,4.0,6.0,8.0,10.0]+divide up a Range into equal-sized sectionsgridSpace (Range 0.0 1.0) 4=[Range 0.0 0.25,Range 0.25 0.5,Range 0.5 0.75,Range 0.75 1.0]D numhask-space'a grid for five-digits per limb species2gridSensible OuterPos False (Range (-12.0) 23.0) 6.[-15.0,-10.0,-5.0,0.0,5.0,10.0,15.0,20.0,25.0]I numhask-space!Monoid based on convex hull unionBCDBCDNone +7>DHVb…+\ numhask-spaceA 2-dim point of a'sAA Point is functorial over both arguments, and is a Num instance.let p = Point 1 1p + p Point 2 2 (2*) <$> p Point 2 2ÕA major reason for this bespoke treatment of a point is that Points do not have maximums and minimums but they form a lattice, and this is useful for folding points to find out the (rectangular) Space they occupy.Point 0 1 /\ Point 1 0 Point 0 0Point 0 1 \/ Point 1 0 Point 1 1^ numhask-space2rotate a point by x degrees relative to the originrotate 90 (Point 0 1)Point 1.0 6.123233995736766e-17_ numhask-space7Create Points for a formulae y = f(x) across an x rangegridP (**2) (Range 0 4) 4H[Point 0.0 0.0,Point 1.0 1.0,Point 2.0 4.0,Point 3.0 9.0,Point 4.0 16.0]\]^_\]^_None+4567=>?DHMVbg¬\x numhask-spaceCa rectangular space often representing a 2-dimensional or XY plane."let a = Rect (-1.0) 1.0 (-2.0) 4.0aRect -1.0 1.0 -2.0 4.0let (Ranges x y) = axRange -1.0 1.0yRange -2.0 4.0fmap (+1) (Rect 1 2 3 4) Rect 2 3 4 5+as a Space instance with Points as ElementsIproject (Rect 0.0 1.0 (-1.0) 0.0) (Rect 1.0 4.0 10.0 0.0) (Point 0.5 1.0)Point 2.5 -10.0;gridSpace (Rect 0.0 10.0 0.0 1.0) (Point (2::Int) (2::Int))W[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.0 10.0 0.0 1.0) (Point (2::Int) (2::Int))=[Point 2.5 0.25,Point 2.5 0.75,Point 7.5 0.25,Point 7.5 0.75]z numhask-spacepattern of Ranges xrange yrange{ numhask-space+pattern of Rect lowerx upperx lowery uppery| numhask-space[create a list of points representing the lower left and upper right corners of a rectangle. corners one[Point -0.5 -0.5,Point 0.5 0.5]} numhask-space the 4 corners corners4 one=[Point -0.5 -0.5,Point -0.5 0.5,Point 0.5 -0.5,Point 0.5 0.5]~ numhask-space5project a Rect from an old Space (Rect) to a new one.^The Space instance of Rect uses Points as Elements, but a Rect can also be a Space over Rects.MprojectRect (Rect 0 1 (-1) 0) (Rect 0 4 0 8) (Rect 0.25 0.75 (-0.75) (-0.25))Rect 1.0 3.0 2.0 6.0 numhask-spaceconvex hull union of Rect'sfoldRect [Rect 0 1 0 1, one]Just Rect -0.5 1.0 -0.5 1.0€ numhask-spaceadd a Point to a RectaddPoint (Point 0 1) oneRect -0.5 0.5 0.5 1.5 numhask-spaceXrotate the corners of a Rect by x degrees relative to the origin, and fold to a new RectrotateRect 45 oneXRect -0.7071067811865475 0.7071067811865475 -5.551115123125783e-17 5.551115123125783e-17‚ numhask-spaceUCreate Rects for a formulae y = f(x) across an x range where the y range is Range 0 ygridR (**2) (Range 0 4) 4Z[Rect 0.0 1.0 0.0 0.25,Rect 1.0 2.0 0.0 2.25,Rect 2.0 3.0 0.0 6.25,Rect 3.0 4.0 0.0 12.25]ƒ numhask-space8Create values c for Rects data for a formulae c = f(x,y)8gridF (\(Point x y) -> x * y) (Rect 0 4 0 4) (Point 2 2)m[(Rect 0.0 2.0 0.0 2.0,1.0),(Rect 0.0 2.0 2.0 4.0,3.0),(Rect 2.0 4.0 0.0 2.0,3.0),(Rect 2.0 4.0 2.0 4.0,9.0)]„ numhask-space8convert a ratio (eg x:1) to a Rect with a height of one.aspect 2Rect -1.0 1.0 -0.5 0.5… numhask-spaceconvert a Rect to a ratioratio (Rect (-1) 1 (-0.5) 0.5)2.0‰ numhask-spaceŸNumeric algebra based on interval arithmetioc for addition and unitRect and projection for multiplication >>> one + one :: Rect Double Rect -1.0 1.0 -1.0 1.0xyz{|}~€‚ƒ„…xy{z|}~€‚ƒ„…None.Dbʆ – numhask-spaceWhether or not to ignore unders and overs. If overs and unders are dealt with, IncludeOvers supplies an assumed width for the outer buckets.™ numhask-spaceÉThis Histogram is a list of contiguous boundaries (a boundary being the lower edge of one bucket and the upper edge of another), and a value (usually a count) for each bucket, represented here as a map?Overs and Unders are contained in key = 0 and key = length cuts numhask-space)Fill a Histogram using pre-specified cutsfill [0,50,100] [1..100]JHistogram {cuts = [0.0,50.0,100.0], values = fromList [(1,50.0),(2,50.0)]}ž numhask-space7find the index of the bucket the value is contained in.Ÿ numhask-spaceNMake a histogram using n equally spaced cuts over the entire range of the dataregular 4 [0..100]nHistogram {cuts = [0.0,25.0,50.0,75.0,100.0], values = fromList [(0,1.0),(1,25.0),(2,25.0),(3,25.0),(4,25.0)]}  numhask-spaceTransform a Histogram to Rects*makeRects IgnoreOvers (regular 4 [0..100])a[Rect 0.0 25.0 0.0 0.25,Rect 25.0 50.0 0.0 0.25,Rect 50.0 75.0 0.0 0.25,Rect 75.0 100.0 0.0 0.25]” numhask-spaceapprox regular n-quantilesregularQuantiles 4 [0..100][0.0,24.75,50.0,75.25,100.0]¢ numhask-space#one-pass approximate quantiles fold£ numhask-space6take a specification of quantiles and make a Histogram?fromQuantiles [0,0.25,0.5,0.75,1] (regularQuantiles 4 [0..100])hHistogram {cuts = [0.0,24.75,50.0,75.25,100.0], values = fromList [(1,0.25),(2,0.25),(3,0.25),(4,0.25)]}¤ numhask-space.normalize a histogram so that sum values = onefreq $ fill [0,50,100] [1..100]HHistogram {cuts = [0.0,50.0,100.0], values = fromList [(1,0.5),(2,0.5)]}–—˜™š›œžŸ ”¢£¤™š›œ–—˜žŸ ”¢£¤None4DbgŃ § numhask-space,unification of a point and rect on the planeŖ numhask-spacemake an XY from a rectangle« numhask-spacemake an XY from a point¬ numhask-spaceConvert a spot to a Rect­ numhask-spaceConvert a spot to a Point® numhask-spaceEproject an XY from one Rect to another, preserving relative position.!projectOn one (Rect 0 1 0 1) zeroPointXY Point -0.5 -0.5Æ numhask-space;project a [Spot a] from it's folded space to the given area9projectTo one (SpotPoint <$> zipWith Point [0..2] [0..2])K[SpotPoint Point -0.5 -0.5,SpotPoint Point 0.0 0.0,SpotPoint Point 0.5 0.5]° numhask-space'guard substituting singleton dimensions §Ø©Ŗ«¬­®Æ° §Ø©«Ŗ¬­®Æ°NoneDbѾm  !"#$%&'()*+,-./0123456789:;<=>BCD\]^_xyz{|}~€‚ƒ„…–—˜™š›œžŸ ”¢£¤§Ø©Ŗ«¬­®Æ°+   "#$ !%&'()*»      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIIJKLMNOPQRSTUVWXYZ[\]^_`abbcdefghijklmnopqrstuvwxyz{|}~}€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ”¢£¤„¦§Ø©Ŗ«¬­®Æ°±²³“µ¶·ø¹ŗ»¼½¾*numhask-space-0.6.1-8gI3hO8hirGDgfjfMfjFFN NumHask.SpaceNumHask.Space.TimeNumHask.Space.RangeNumHask.Space.PointNumHask.Space.RectNumHask.Space.HistogramNumHask.Space.XYNumHask.Space.TypesPosOuterPosInnerPosLowerPosUpperPosMidPos FieldSpaceGridgrid gridSpace IntersectiongetIntersectionUniongetUnionSpaceElementlowerupper singleton intersectionunionnorm...>.<|.||>||<|containsdisjointmemberOfwidth+/-midprojectspace1monotoneepswidenwidenEpsscalemovePosDiscontinuous PosInnerOnlyPosIncludeBoundaries TimeGrainYearsMonthsDaysHoursMinutesSeconds parseUTCTimefromNominalDiffTimetoNominalDiffTime fromDiffTime toDiffTime floorGrain ceilingGrainplacedTimeLabelDiscontinuousplacedTimeLabelContinuoussensibleTimeGrid$fShowTimeGrain $fEqTimeGrain$fGenericTimeGrainRange gridSensible $fSignedRange$fMultiplicativeRange$fSubtractiveRange$fAdditiveRange$fSemigroupRange$fFieldSpaceRange $fSpaceRange$fMeetSemiLatticeRange$fJoinSemiLatticeRange$fRepresentableRange$fDistributiveRange$fTraversable1Range$fTraversableRange$fFoldable1Range$fFoldableRange$fApplicativeRange $fApplyRange$fFunctorRange $fShow1Range $fEq1Range $fShowRange $fEqRange$fGenericRangePointrotategridP$fMeetSemiLatticePoint$fJoinSemiLatticePoint$fRepresentablePoint$fDistributivePoint$fDivisivePoint $fSignedPoint $fFieldPoint$fDistributivePoint0$fMultiplicativePoint$fSubtractivePoint$fAdditivePoint$fBoundedPoint $fMonoidPoint$fSemigroupPoint$fTraversablePoint$fFoldablePoint $fMonadPoint$fApplicativePoint $fShow1Point $fEq1Point$fFunctorPoint $fShowPoint $fEqPoint$fGenericPointRectRect'Rangescornerscorners4 projectRectfoldRectaddPoint rotateRectgridRgridFaspectratio $fSignedRect$fMultiplicativeRect$fSubtractiveRect$fAdditiveRect$fFieldSpaceRect $fSpaceRect$fSemigroupRect$fRepresentableRect$fDistributiveRect $fShowRect$fEqRect $fFunctorRect$fApplicativeRect$fFoldableRect$fTraversableRect $fGenericRect DealOvers IgnoreOvers IncludeOvers HistogramcutsvaluesfillcutIregular makeRectsregularQuantiles quantileFold fromQuantilesfreq$fShowHistogram $fEqHistogramXYPointXYRectXYRPtoRecttoPoint projectOn projectTofixRect $fSemigroupXY $fSignedXY$fSubtractiveXY$fMultiplicativeXY $fAdditiveXY$fEqXY$fShowXY $fFunctorXYaddGrainstepSensibleTime