-- |-- Module : Data.IntervalMap.Interval-- Copyright : (c) Christoph Breitkopf 2011-- License : BSD-style-- Maintainer : chris@chr-breitkopf.de-- Stability : experimental-- Portability : portable---- A conservative implementation of Intervals, mostly for use as keys in-- a 'Data.IntervalMap'.---- This should really be a typeclass, so you could have a tuple be an instance-- of Interval, but that is currently not possible in standard Haskell.---- The contructor names of the half-open intervals seem somewhat clumsy,-- and I'm open to suggestions for better names.--moduleData.IntervalMap.Interval(-- * Interval typeInterval(..),-- * QuerylowerBound,upperBound,leftClosed,rightClosed,isEmpty,-- * Interval operationsoverlaps,subsumes,before,after,compareByUpper,-- * Point operationsbelow,inside,above)whereimportControl.DeepSeq(NFData(rnf))-- | Intervals with endpoints of type @a@.---- 'Read' and 'Show' use mathematical notation with square brackets for closed-- and parens for open intervals.-- This is better for human readability, but is not a valid Haskell expression.-- Closed intervals look like a list, open intervals look like a tuple,-- and half-open intervals look like mismatched parens.dataIntervala=IntervalCO!a!a-- ^ Including lower bound, excluding upper|ClosedInterval!a!a-- ^ Closed at both ends|OpenInterval!a!a-- ^ Open at both ends|IntervalOC!a!a-- ^ Excluding lower bound, including upperderiving(Eq)instanceShowa=>Show(Intervala)whereshowsPrec_(IntervalCOab)=showChar'['.showsa.showChar','.showsb.showChar')'showsPrec_(ClosedIntervalab)=showChar'['.showsa.showChar','.showsb.showChar']'showsPrec_(OpenIntervalab)=showChar'('.showsa.showChar','.showsb.showChar')'showsPrec_(IntervalOCab)=showChar'('.showsa.showChar','.showsb.showChar']'instanceReada=>Read(Intervala)wherereadsPrec_=readParenFalse(\r->[(ClosedIntervalab,w)|("[",s)<-lexr,(a,t)<-readss,(",",u)<-lext,(b,v)<-readsu,("]",w)<-lexv]++[(OpenIntervalab,w)|("(",s)<-lexr,(a,t)<-readss,(",",u)<-lext,(b,v)<-readsu,(")",w)<-lexv]++[(IntervalCOab,w)|("[",s)<-lexr,(a,t)<-readss,(",",u)<-lext,(b,v)<-readsu,(")",w)<-lexv]++[(IntervalOCab,w)|("(",s)<-lexr,(a,t)<-readss,(",",u)<-lext,(b,v)<-readsu,("]",w)<-lexv])-- compare only the lower boundcompareL::Orda=>Intervala->Intervala->OrderingcompareL(IntervalCOa_)(IntervalCOb_)=compareabcompareL(IntervalCOa_)(ClosedIntervalb_)=compareabcompareL(IntervalCOa_)(OpenIntervalb_)=ifa<=bthenLTelseGTcompareL(IntervalCOa_)(IntervalOCb_)=ifa<=bthenLTelseGTcompareL(ClosedIntervala_)(IntervalCOb_)=compareabcompareL(ClosedIntervala_)(ClosedIntervalb_)=compareabcompareL(ClosedIntervala_)(OpenIntervalb_)=ifa<=bthenLTelseGTcompareL(ClosedIntervala_)(IntervalOCb_)=ifa<=bthenLTelseGTcompareL(OpenIntervala_)(IntervalCOb_)=ifa<bthenLTelseGTcompareL(OpenIntervala_)(ClosedIntervalb_)=ifa<bthenLTelseGTcompareL(OpenIntervala_)(OpenIntervalb_)=compareabcompareL(OpenIntervala_)(IntervalOCb_)=compareabcompareL(IntervalOCa_)(IntervalCOb_)=ifa<bthenLTelseGTcompareL(IntervalOCa_)(ClosedIntervalb_)=ifa<bthenLTelseGTcompareL(IntervalOCa_)(OpenIntervalb_)=compareabcompareL(IntervalOCa_)(IntervalOCb_)=compareab{-# INLINE compareL #-}-- compare only the upper boundcompareU::Orda=>Intervala->Intervala->OrderingcompareU(IntervalCO_a)(IntervalCO_b)=compareabcompareU(IntervalCO_a)(ClosedInterval_b)=ifa<=bthenLTelseGTcompareU(IntervalCO_a)(OpenInterval_b)=compareabcompareU(IntervalCO_a)(IntervalOC_b)=ifa<=bthenLTelseGTcompareU(ClosedInterval_a)(IntervalCO_b)=ifa<bthenLTelseGTcompareU(ClosedInterval_a)(ClosedInterval_b)=compareabcompareU(ClosedInterval_a)(OpenInterval_b)=ifa<bthenLTelseGTcompareU(ClosedInterval_a)(IntervalOC_b)=compareabcompareU(OpenInterval_a)(IntervalCO_b)=compareabcompareU(OpenInterval_a)(ClosedInterval_b)=ifa<=bthenLTelseGTcompareU(OpenInterval_a)(OpenInterval_b)=compareabcompareU(OpenInterval_a)(IntervalOC_b)=ifa<=bthenLTelseGTcompareU(IntervalOC_a)(IntervalCO_b)=ifa<bthenLTelseGTcompareU(IntervalOC_a)(ClosedInterval_b)=compareabcompareU(IntervalOC_a)(OpenInterval_b)=ifa<bthenLTelseGTcompareU(IntervalOC_a)(IntervalOC_b)=compareab{-# INLINE compareU #-}instanceOrda=>Ord(Intervala)wherecompareab=casecompareLabofEQ->compareUabr->rinstanceFunctorIntervalwherefmapf(IntervalCOab)=IntervalCO(fa)(fb)fmapf(ClosedIntervalab)=ClosedInterval(fa)(fb)fmapf(OpenIntervalab)=OpenInterval(fa)(fb)fmapf(IntervalOCab)=IntervalOC(fa)(fb)instanceNFDataa=>NFData(Intervala)wherernf(IntervalCOab)=rnfa`seq`rnfbrnf(ClosedIntervalab)=rnfa`seq`rnfbrnf(OpenIntervalab)=rnfa`seq`rnfbrnf(IntervalOCab)=rnfa`seq`rnfb-- | Like 'compare', but considering the upper bound first.compareByUpper::Orda=>Intervala->Intervala->OrderingcompareByUpperab=casecompareUabofEQ->compareLabr->r-- | Get the lower bound.lowerBound::Intervala->alowerBound(ClosedIntervallo_)=lolowerBound(OpenIntervallo_)=lolowerBound(IntervalCOlo_)=lolowerBound(IntervalOClo_)=lo-- | Get the upper bound.upperBound::Intervala->aupperBound(ClosedInterval_hi)=hiupperBound(OpenInterval_hi)=hiupperBound(IntervalCO_hi)=hiupperBound(IntervalOC_hi)=hi-- | Is the interval empty?isEmpty::(Orda)=>Intervala->BoolisEmpty(ClosedIntervalab)=a>bisEmptyiv=lowerBoundiv>=upperBoundiv-- | Does the interval include its lower bound?leftClosed::Intervala->BoolleftClosed(ClosedInterval__)=TrueleftClosed(IntervalCO__)=TrueleftClosed_=False-- | Does the interval include its upper bound?rightClosed::Intervala->BoolrightClosed(ClosedInterval__)=TruerightClosed(IntervalOC__)=TruerightClosed_=False-- | Do the two intervals overlap?overlaps::(Orda)=>Intervala->Intervala->Booloverlaps(ClosedIntervallo1hi1)(ClosedIntervallo2hi2)=lo1<=hi2&&hi1>=lo2overlaps(ClosedIntervallo1hi1)(OpenIntervallo2hi2)=lo1<hi2&&hi1>lo2overlaps(ClosedIntervallo1hi1)(IntervalCOlo2hi2)=lo1<hi2&&hi1>=lo2overlaps(ClosedIntervallo1hi1)(IntervalOClo2hi2)=lo1<=hi2&&hi1>lo2overlaps(OpenIntervallo1hi1)(ClosedIntervallo2hi2)=lo1<hi2&&hi1>lo2overlaps(OpenIntervallo1hi1)(OpenIntervallo2hi2)=lo1<hi2&&hi1>lo2overlaps(OpenIntervallo1hi1)(IntervalCOlo2hi2)=lo1<hi2&&hi1>lo2overlaps(OpenIntervallo1hi1)(IntervalOClo2hi2)=lo1<hi2&&hi1>lo2overlaps(IntervalCOlo1hi1)(ClosedIntervallo2hi2)=lo1<=hi2&&hi1>lo2overlaps(IntervalCOlo1hi1)(OpenIntervallo2hi2)=lo1<hi2&&hi1>lo2overlaps(IntervalCOlo1hi1)(IntervalCOlo2hi2)=lo1<hi2&&hi1>lo2overlaps(IntervalCOlo1hi1)(IntervalOClo2hi2)=lo1<=hi2&&hi1>lo2overlaps(IntervalOClo1hi1)(ClosedIntervallo2hi2)=lo1<hi2&&hi1>=lo2overlaps(IntervalOClo1hi1)(OpenIntervallo2hi2)=lo1<hi2&&hi1>lo2overlaps(IntervalOClo1hi1)(IntervalCOlo2hi2)=lo1<hi2&&hi1>=lo2overlaps(IntervalOClo1hi1)(IntervalOClo2hi2)=lo1<hi2&&hi1>lo2-- | Does the first interval completely contain the second?subsumes::(Orda)=>Intervala->Intervala->Boolsubsumes(ClosedIntervallo1hi1)(ClosedIntervallo2hi2)=lo1<=lo2&&hi1>=hi2subsumes(ClosedIntervallo1hi1)(OpenIntervallo2hi2)=lo1<=lo2&&hi1>=hi2subsumes(ClosedIntervallo1hi1)(IntervalCOlo2hi2)=lo1<=lo2&&hi1>=hi2subsumes(ClosedIntervallo1hi1)(IntervalOClo2hi2)=lo1<=lo2&&hi1>=hi2subsumes(OpenIntervallo1hi1)(ClosedIntervallo2hi2)=lo1<lo2&&hi1>hi2subsumes(OpenIntervallo1hi1)(OpenIntervallo2hi2)=lo1<=lo2&&hi1>=hi2subsumes(OpenIntervallo1hi1)(IntervalCOlo2hi2)=lo1<lo2&&hi1>=hi2subsumes(OpenIntervallo1hi1)(IntervalOClo2hi2)=lo1<=lo2&&hi1>hi2subsumes(IntervalCOlo1hi1)(ClosedIntervallo2hi2)=lo1<=lo2&&hi1>hi2subsumes(IntervalCOlo1hi1)(OpenIntervallo2hi2)=lo1<=lo2&&hi1>=hi2subsumes(IntervalCOlo1hi1)(IntervalCOlo2hi2)=lo1<=lo2&&hi1>=hi2subsumes(IntervalCOlo1hi1)(IntervalOClo2hi2)=lo1<=lo2&&hi1>hi2subsumes(IntervalOClo1hi1)(ClosedIntervallo2hi2)=lo1<lo2&&hi1>=hi2subsumes(IntervalOClo1hi1)(OpenIntervallo2hi2)=lo1<=lo2&&hi1>=hi2subsumes(IntervalOClo1hi1)(IntervalCOlo2hi2)=lo1<lo2&&hi1>=hi2subsumes(IntervalOClo1hi1)(IntervalOClo2hi2)=lo1<=lo2&&hi1>=hi2-- | Interval strictly before another?-- True if the upper bound of the first interval is below the lower bound of the second.before::Orda=>Intervala->Intervala->BoolIntervalCO_l`before`r=l<=lowerBoundrClosedInterval_l`before`IntervalCOr_=l<rClosedInterval_l`before`ClosedIntervalr_=l<rClosedInterval_l`before`OpenIntervalr_=l<=rClosedInterval_l`before`IntervalOCr_=l<=rOpenInterval_l`before`r=l<=lowerBoundrIntervalOC_l`before`IntervalCOr_=l<rIntervalOC_l`before`ClosedIntervalr_=l<rIntervalOC_l`before`OpenIntervalr_=l<=rIntervalOC_l`before`IntervalOCr_=l<=r-- | Interval strictly after another?-- Same as 'flip before'.after::Orda=>Intervala->Intervala->Boolr`after`l=l`before`r{-# INLINE after #-}-- | Does the interval contain a given point?inside::(Orda)=>a->Intervala->Boolp`inside`(IntervalCOlohi)=lo<=p&&p<hip`inside`(ClosedIntervallohi)=lo<=p&&p<=hip`inside`(OpenIntervallohi)=lo<p&&p<hip`inside`(IntervalOClohi)=lo<p&&p<=hi-- | Is a point strictly less than lower bound?below::(Orda)=>a->Intervala->Boolp`below`(IntervalCOl_)=p<lp`below`(ClosedIntervall_)=p<lp`below`(OpenIntervall_)=p<=lp`below`(IntervalOCl_)=p<=l-- | Is a point strictly greater than upper bound?above::(Orda)=>a->Intervala->Boolp`above`(IntervalCO_u)=p>=up`above`(ClosedInterval_u)=p>up`above`(OpenInterval_u)=p>=up`above`(IntervalOC_u)=p>u