{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE FlexibleInstances #-}
{-|
Module      : Interval Algebra Utilities
Description : Functions for operating on containers of Intervals.
Copyright   : (c) NoviSci, Inc 2020
License     : BSD3
Maintainer  : bsaul@novisci.com
Stability   : experimental
-}

module IntervalAlgebra.IntervalUtilities (
      combineIntervals
    , combineIntervals'
    , gaps
    , gaps'
    , durations
    , clip
    , relations
    , relations'
    , gapsWithin
    , nothingIf
    , nothingIfNone
    , nothingIfAny
    , nothingIfAll

    -- * Filtering functions
    , filterBefore
    , filterMeets
    , filterOverlaps
    , filterFinishedBy
    , filterContains
    , filterStarts
    , filterEquals
    , filterStartedBy
    , filterDuring
    , filterFinishes
    , filterOverlappedBy
    , filterMetBy
    , filterAfter
    , filterDisjoint
    , filterNotDisjoint
    , filterWithin

) where

import GHC.Base
    ( otherwise, ($), (.), (<*>), seq, not
    , Semigroup((<>))
    , Functor(fmap)
    , Applicative(pure)
    , Int, Bool)
import GHC.Num ()
import Data.Tuple ( fst )
import Data.Foldable ( Foldable(null, foldl', toList), all, any )
import Data.Monoid ( (<>), Monoid(mempty) )
import IntervalAlgebra
    ( Interval, Intervallic(..), IntervalAlgebraic(..)
    , IntervalCombinable(..), IntervalSizeable(..)
    , IntervalRelation(..)
    , ComparativePredicateOf)
import Data.Maybe (mapMaybe, catMaybes, fromMaybe, Maybe(..))
import Data.List ( (++), map, head, init, last, tail )
import Witherable ( Filterable(filter) )

-------------------------------------------------
-- Unexported utilties used in functions below --
-------------------------------------------------

intInt :: Int -> Int -> Interval Int
intInt :: Int -> Int -> Interval Int
intInt = Int -> Int -> Interval Int
forall a. Intervallic a => a -> a -> Interval a
unsafeInterval

-- Fold over consecutive pairs of foldable structure and collect the results in 
-- a monoidal structure.
foldlAccume :: (Foldable f, Applicative m, Monoid (m a))=>
      (b -> b -> a) -- ^ @f@: a function to apply to consecutive elements of @f b@
    -> f b
    -> m a
foldlAccume :: (b -> b -> a) -> f b -> m a
foldlAccume b -> b -> a
f f b
x = (m a, Maybe b) -> m a
forall a b. (a, b) -> a
fst ((m a, Maybe b) -> m a) -> (m a, Maybe b) -> m a
forall a b. (a -> b) -> a -> b
$ ((m a, Maybe b) -> b -> (m a, Maybe b))
-> (m a, Maybe b) -> f b -> (m a, Maybe b)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' ((b -> b -> a) -> (m a, Maybe b) -> b -> (m a, Maybe b)
forall (f :: * -> *) a b.
(Monoid (f a), Applicative f) =>
(b -> b -> a) -> (f a, Maybe b) -> b -> (f a, Maybe b)
applyAccume b -> b -> a
f) (m a
forall a. Monoid a => a
mempty, Maybe b
forall a. Maybe a
Nothing) f b
x

-- Apply a function and accumulate the results in a monoidal structure.
applyAccume :: (Monoid (f a), Applicative f) =>
       (b -> b -> a)  -- ^ @f@: a function combining two @b@s to get an @a@
    -> (f a, Maybe b) -- ^ a pair (accumulating monoid for @b@s, optional @a@)
    -> b              -- ^ this will be the second argument to @f@
    -> (f a, Maybe b)
applyAccume :: (b -> b -> a) -> (f a, Maybe b) -> b -> (f a, Maybe b)
applyAccume b -> b -> a
f (f a
fs, Maybe b
Nothing) b
x = (f a
fs, b -> Maybe b
forall a. a -> Maybe a
Just b
x)
applyAccume b -> b -> a
f (f a
fs, Just b
x)  b
y  = (f a
fs f a -> f a -> f a
forall a. Semigroup a => a -> a -> a
<> a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (b -> b -> a
f b
x b
y), b -> Maybe b
forall a. a -> Maybe a
Just b
y)

-- Lifts a list to a foldable, applicative monoid 
liftListToFoldable :: (Applicative f
                      , Monoid (f a)
                      , Foldable f) =>
    [a] -> f a
liftListToFoldable :: [a] -> f a
liftListToFoldable = (f a -> a -> f a) -> f a -> [a] -> f a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\f a
x a
y -> f a
x f a -> f a -> f a
forall a. Semigroup a => a -> a -> a
<> a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
y) f a
forall a. Monoid a => a
mempty

-- Box to avoid overlapping instances
newtype Box a = Box { Box a -> [a]
unBox :: [a] }

-- Defines how a Box of Intervals are combined. Specifically, the last element of
-- x and first element of y are combined by '<+>'.
instance (IntervalCombinable a) => Semigroup (Box (Interval a)) where
    Box [Interval a]
x <> :: Box (Interval a) -> Box (Interval a) -> Box (Interval a)
<> Box [Interval a]
y
       | [Interval a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Interval a]
x         = [Interval a] -> Box (Interval a)
forall a. [a] -> Box a
Box [Interval a]
y
       | [Interval a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Interval a]
y         = [Interval a] -> Box (Interval a)
forall a. [a] -> Box a
Box [Interval a]
x
       | Bool
otherwise      = [Interval a] -> Box (Interval a)
forall a. [a] -> Box a
Box ([Interval a] -> Box (Interval a))
-> [Interval a] -> Box (Interval a)
forall a b. (a -> b) -> a -> b
$ [Interval a] -> [Interval a]
forall a. [a] -> [a]
init [Interval a]
x [Interval a] -> [Interval a] -> [Interval a]
forall a. [a] -> [a] -> [a]
++ (Interval a
lx Interval a -> Interval a -> [Interval a]
forall a (f :: * -> *).
(IntervalCombinable a, Semigroup (f (Interval a)),
 Applicative f) =>
Interval a -> Interval a -> f (Interval a)
<+> Interval a
fy) [Interval a] -> [Interval a] -> [Interval a]
forall a. [a] -> [a] -> [a]
++ [Interval a] -> [Interval a]
forall a. [a] -> [a]
tail [Interval a]
y
       where lx :: Interval a
lx = [Interval a] -> Interval a
forall a. [a] -> a
last [Interval a]
x
             fy :: Interval a
fy = [Interval a] -> Interval a
forall a. [a] -> a
head [Interval a]
y

-------------------------------------------------

-- | Returns a container of intervals where any intervals that meet or share support
--   are combined into one interval. *To work properly, the input should 
--   be sorted*. See 'combineIntervals'' for a version that works only on lists.
--
-- >>> combineIntervals [intInt 0 10, intInt 2 7, intInt 10 12, intInt 13 15]
-- [(0, 12),(13, 15)]
combineIntervals :: (IntervalCombinable a
         , Applicative f
         , Monoid (f (Interval a))
         , Foldable f) =>
      f (Interval a) ->
      f (Interval a)
combineIntervals :: f (Interval a) -> f (Interval a)
combineIntervals f (Interval a)
x = [Interval a] -> f (Interval a)
forall (f :: * -> *) a.
(Applicative f, Monoid (f a), Foldable f) =>
[a] -> f a
liftListToFoldable ([Interval a] -> [Interval a]
forall a. IntervalCombinable a => [Interval a] -> [Interval a]
combineIntervals' ([Interval a] -> [Interval a]) -> [Interval a] -> [Interval a]
forall a b. (a -> b) -> a -> b
$ f (Interval a) -> [Interval a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList f (Interval a)
x)

-- | Returns a list of intervals where any intervals that meet or share support
--   are combined into one interval. *To work properly, the input list should 
--   be sorted*. 
--
-- >>> combineIntervals' [intInt 0 10, intInt 2 7, intInt 10 12, intInt 13 15]
-- [(0, 12),(13, 15)]
combineIntervals' :: (IntervalCombinable a) => [Interval a] -> [Interval a]
combineIntervals' :: [Interval a] -> [Interval a]
combineIntervals' [Interval a]
l = Box (Interval a) -> [Interval a]
forall a. Box a -> [a]
unBox (Box (Interval a) -> [Interval a])
-> Box (Interval a) -> [Interval a]
forall a b. (a -> b) -> a -> b
$ (Box (Interval a) -> Box (Interval a) -> Box (Interval a))
-> Box (Interval a) -> [Box (Interval a)] -> Box (Interval a)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Box (Interval a) -> Box (Interval a) -> Box (Interval a)
forall a. Semigroup a => a -> a -> a
(<>) ([Interval a] -> Box (Interval a)
forall a. [a] -> Box a
Box []) ((Interval a -> Box (Interval a))
-> [Interval a] -> [Box (Interval a)]
forall a b. (a -> b) -> [a] -> [b]
map (\Interval a
z -> [Interval a] -> Box (Interval a)
forall a. [a] -> Box a
Box [Interval a
z]) [Interval a]
l)

-- | Returns a (possibly empty) container of intervals consisting of the gaps 
--   between intervals in the input. *To work properly, the input should be
--   sorted*. See 'gaps'' for a version that returns a list.
--
-- >>> gaps [intInt 1 5, intInt 8 12, intInt 11 14]
-- [(5, 8)]
gaps :: (IntervalCombinable a
         , Applicative f
         , Monoid (f (Interval a))
         , Foldable f) =>
      f (Interval a) ->
      f (Interval a)
gaps :: f (Interval a) -> f (Interval a)
gaps f (Interval a)
x = [Interval a] -> f (Interval a)
forall (f :: * -> *) a.
(Applicative f, Monoid (f a), Foldable f) =>
[a] -> f a
liftListToFoldable (f (Interval a) -> [Interval a]
forall a (f :: * -> *).
(IntervalCombinable a, Applicative f, Monoid (f (Interval a)),
 Foldable f) =>
f (Interval a) -> [Interval a]
gaps' f (Interval a)
x)

-- | Returns a (possibly empty) list of intervals consisting of the gaps between
--   intervals in the input container. *To work properly, the input should be 
--   sorted*. This version outputs a list. See 'gaps' for a version that lifts
--   the result to same input structure @f@.
gaps' :: (IntervalCombinable a
         , Applicative f
         , Monoid (f (Interval a))
         , Foldable f) =>
      f (Interval a) ->
      [Interval a]
gaps' :: f (Interval a) -> [Interval a]
gaps' f (Interval a)
x = [Maybe (Interval a)] -> [Interval a]
forall a. [Maybe a] -> [a]
catMaybes ((Interval a -> Interval a -> Maybe (Interval a))
-> f (Interval a) -> [Maybe (Interval a)]
forall (f :: * -> *) (m :: * -> *) a b.
(Foldable f, Applicative m, Monoid (m a)) =>
(b -> b -> a) -> f b -> m a
foldlAccume Interval a -> Interval a -> Maybe (Interval a)
forall a.
IntervalCombinable a =>
Interval a -> Interval a -> Maybe (Interval a)
(><) f (Interval a)
x)

-- | Returns the 'duration' of each 'Interval' in the 'Functor' @f@.
--
-- >>> durations [intInt 1 10, intInt 2 12, intInt 5 6]
-- [9,10,1]
durations :: (Functor f, IntervalSizeable a b)=>
       f (Interval a)
    -> f b
durations :: f (Interval a) -> f b
durations = (Interval a -> b) -> f (Interval a) -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Interval a -> b
forall a b. IntervalSizeable a b => Interval a -> b
duration

-- | In the case that x y are not disjoint, clips y to the extent of x.
-- 
-- >>> clip (intInt 0 5) (intInt 3 6)
-- Just (3, 5)
--
-- >>> clip (intInt 0 3) (intInt 4 6)
-- Nothing
clip :: (IntervalAlgebraic a, IntervalSizeable a b)=>
       Interval a
    -> Interval a
    -> Maybe (Interval a)
clip :: Interval a -> Interval a -> Maybe (Interval a)
clip Interval a
x Interval a
y
   | ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
overlaps Interval a
x Interval a
y     = Interval a -> Maybe (Interval a)
forall a. a -> Maybe a
Just (Interval a -> Maybe (Interval a))
-> Interval a -> Maybe (Interval a)
forall a b. (a -> b) -> a -> b
$ b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
enderval   (a -> a -> b
forall a b. IntervalSizeable a b => a -> a -> b
diff (Interval a -> a
forall a. Intervallic a => Interval a -> a
end Interval a
x) (Interval a -> a
forall a. Intervallic a => Interval a -> a
begin Interval a
y)) (Interval a -> a
forall a. Intervallic a => Interval a -> a
end Interval a
x)
   | ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
overlappedBy Interval a
x Interval a
y = Interval a -> Maybe (Interval a)
forall a. a -> Maybe a
Just (Interval a -> Maybe (Interval a))
-> Interval a -> Maybe (Interval a)
forall a b. (a -> b) -> a -> b
$ b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
beginerval (a -> a -> b
forall a b. IntervalSizeable a b => a -> a -> b
diff (Interval a -> a
forall a. Intervallic a => Interval a -> a
end Interval a
y) (Interval a -> a
forall a. Intervallic a => Interval a -> a
begin Interval a
x)) (Interval a -> a
forall a. Intervallic a => Interval a -> a
begin Interval a
x)
   | ComparativePredicateOf (Interval a)
jx Interval a
x Interval a
y           = Interval a -> Maybe (Interval a)
forall a. a -> Maybe a
Just Interval a
x
   | ComparativePredicateOf (Interval a)
jy Interval a
x Interval a
y           = Interval a -> Maybe (Interval a)
forall a. a -> Maybe a
Just Interval a
y
   | ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
disjoint Interval a
x Interval a
y     = Maybe (Interval a)
forall a. Maybe a
Nothing
   where jy :: ComparativePredicateOf (Interval a)
jy = ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
equals ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
<|> ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
startedBy ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
<|> ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
contains ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
<|> ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
finishedBy
         jx :: ComparativePredicateOf (Interval a)
jx = ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
starts ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
<|> ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
during ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
-> ComparativePredicateOf (Interval a)
<|> ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
finishes

-- | Returns a list of the 'IntervalRelation' between each consecutive pair 
--   of intervals. This the specialized form of 'relations'' which can return
--   any 'Applicative', 'Monoid' structure.
--
-- >>> relations [intInt 0 1, intInt 1 2] 
-- [Meets]
relations :: (IntervalAlgebraic a, Foldable f)=>
       f (Interval a)
    -> [IntervalRelation a]
relations :: f (Interval a) -> [IntervalRelation a]
relations = f (Interval a) -> [IntervalRelation a]
forall a (f :: * -> *) (m :: * -> *).
(IntervalAlgebraic a, Foldable f, Applicative m,
 Monoid (m (IntervalRelation a))) =>
f (Interval a) -> m (IntervalRelation a)
relations'

-- | A generic form of 'relations' which can output any 'Applicative' and 
--   'Monoid' structure. 
-- >>> (relations' [intInt 0 1, intInt 1 2]) :: [IntervalRelation Int]
-- [Meets]
relations' :: ( IntervalAlgebraic a
              , Foldable f
              , Applicative m
              , Monoid (m (IntervalRelation a)) )=>
        f (Interval a)
     -> m (IntervalRelation a)
relations' :: f (Interval a) -> m (IntervalRelation a)
relations' = (Interval a -> Interval a -> IntervalRelation a)
-> f (Interval a) -> m (IntervalRelation a)
forall (f :: * -> *) (m :: * -> *) a b.
(Foldable f, Applicative m, Monoid (m a)) =>
(b -> b -> a) -> f b -> m a
foldlAccume Interval a -> Interval a -> IntervalRelation a
forall a.
IntervalAlgebraic a =>
Interval a -> Interval a -> IntervalRelation a
relate

-- | Applies 'gaps' to all the non-disjoint intervals in @x@ that are *not* disjoint
-- from @i@. Intervals that 'overlaps' or are 'overlappedBy' @i@ are 'clip'ped 
-- to @i@, so that all the intervals are 'within' @i@. If there are no gaps, then
-- 'Nothing' is returned.
--
-- >>> gapsWithin (intInt 1 10) [intInt 0 5, intInt 7 9, intInt 12 15]
-- Just [(5, 7),(9, 10)]
--
gapsWithin :: ( Applicative f
               , Foldable f
               , Monoid (f (Interval a))
               , IntervalSizeable a b
               , IntervalCombinable a
               , Filterable f
               , IntervalAlgebraic a)=>
     Interval a     -- ^ i
  -> f (Interval a) -- ^ x
  -> Maybe (f (Interval a))
gapsWithin :: Interval a -> f (Interval a) -> Maybe (f (Interval a))
gapsWithin Interval a
i f (Interval a)
x 
  | f (Interval a) -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null f (Interval a)
ivs  = Maybe (f (Interval a))
forall a. Maybe a
Nothing  
  | Bool
otherwise = f (Interval a) -> Maybe (f (Interval a))
forall a. a -> Maybe a
Just (f (Interval a) -> Maybe (f (Interval a)))
-> f (Interval a) -> Maybe (f (Interval a))
forall a b. (a -> b) -> a -> b
$ f (Interval a) -> f (Interval a)
forall a (f :: * -> *).
(IntervalCombinable a, Applicative f, Monoid (f (Interval a)),
 Foldable f) =>
f (Interval a) -> f (Interval a)
gaps (f (Interval a) -> f (Interval a))
-> f (Interval a) -> f (Interval a)
forall a b. (a -> b) -> a -> b
$ Interval a -> f (Interval a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Interval a
s f (Interval a) -> f (Interval a) -> f (Interval a)
forall a. Semigroup a => a -> a -> a
<> f (Interval a)
ivs f (Interval a) -> f (Interval a) -> f (Interval a)
forall a. Semigroup a => a -> a -> a
<> Interval a -> f (Interval a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Interval a
e
        where s :: Interval a
s   = b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
enderval   b
0 (Interval a -> a
forall a. Intervallic a => Interval a -> a
begin Interval a
i)
              e :: Interval a
e   = b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
beginerval b
0 (Interval a -> a
forall a. Intervallic a => Interval a -> a
end Interval a
i)
              nd :: [Interval a]
nd  = f (Interval a) -> [Interval a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
Interval a -> f (Interval a) -> f (Interval a)
filterNotDisjoint Interval a
i f (Interval a)
x)
              ivs :: f (Interval a)
ivs = [Interval a] -> f (Interval a)
forall (f :: * -> *) a.
(Applicative f, Monoid (f a), Foldable f) =>
[a] -> f a
liftListToFoldable ((Interval a -> Maybe (Interval a)) -> [Interval a] -> [Interval a]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Interval a -> Interval a -> Maybe (Interval a)
forall a b.
(IntervalAlgebraic a, IntervalSizeable a b) =>
Interval a -> Interval a -> Maybe (Interval a)
clip Interval a
i) [Interval a]
nd) 

-- | Given a predicate combinator, a predicate, and list of intervals, returns 
--   the input unchanged if the predicate combinator is @True@. Otherwise, returns
--   an empty list. See 'nothingIfAny' and 'nothingIfNone' for examples.
nothingIf :: (Monoid (f (Interval a)), Filterable f, IntervalAlgebraic a)=>
     ((Interval a -> Bool) -> f (Interval a) -> Bool) -- ^ e.g. 'any' or 'all'
  -> (Interval a -> Bool) -- ^ predicate to apply to each element of input list
  -> f (Interval a)
  -> Maybe (f (Interval a))
nothingIf :: ((Interval a -> Bool) -> f (Interval a) -> Bool)
-> (Interval a -> Bool) -> f (Interval a) -> Maybe (f (Interval a))
nothingIf (Interval a -> Bool) -> f (Interval a) -> Bool
quantifier Interval a -> Bool
predicate f (Interval a)
x = if (Interval a -> Bool) -> f (Interval a) -> Bool
quantifier Interval a -> Bool
predicate f (Interval a)
x then Maybe (f (Interval a))
forall a. Maybe a
Nothing else f (Interval a) -> Maybe (f (Interval a))
forall a. a -> Maybe a
Just f (Interval a)
x

-- | Returns the empty monoid structure if *none* of the element of input satisfy
--   the predicate condition.
-- 
-- For example, the following returns the empty list because none of the intervals
-- in the input list 'starts' (3, 5).
--
-- >>> nothingIfNone (starts (intInt 3 5)) [intInt 3 4, intInt 5 6]
-- Nothing
--
-- In the following, (3, 5) 'starts' (3, 6), so the input is returned.
--
-- >>> nothingIfNone (starts (intInt 3 5)) [intInt 3 6, intInt 5 6]
-- Just [(3, 6),(5, 6)]
--
nothingIfNone :: (Monoid (f (Interval a)), Foldable f, Filterable f, IntervalAlgebraic a)=>
    (Interval a -> Bool) -- ^ predicate to apply to each element of input list
  -> f (Interval a)
  -> Maybe (f (Interval a))
nothingIfNone :: (Interval a -> Bool) -> f (Interval a) -> Maybe (f (Interval a))
nothingIfNone = ((Interval a -> Bool) -> f (Interval a) -> Bool)
-> (Interval a -> Bool) -> f (Interval a) -> Maybe (f (Interval a))
forall (f :: * -> *) a.
(Monoid (f (Interval a)), Filterable f, IntervalAlgebraic a) =>
((Interval a -> Bool) -> f (Interval a) -> Bool)
-> (Interval a -> Bool) -> f (Interval a) -> Maybe (f (Interval a))
nothingIf (\Interval a -> Bool
f f (Interval a)
x -> (Bool -> Bool
not(Bool -> Bool)
-> (f (Interval a) -> Bool) -> f (Interval a) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Interval a -> Bool) -> f (Interval a) -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Interval a -> Bool
f) f (Interval a)
x)

-- | Returns the empty monoid structure if *any* of the element of input satisfy
--   the predicate condition
nothingIfAny :: (Monoid (f (Interval a)), Foldable f, Filterable f, IntervalAlgebraic a)=>
    (Interval a -> Bool) -- ^ predicate to apply to each element of input list
  -> f (Interval a)
  -> Maybe (f (Interval a))
nothingIfAny :: (Interval a -> Bool) -> f (Interval a) -> Maybe (f (Interval a))
nothingIfAny = ((Interval a -> Bool) -> f (Interval a) -> Bool)
-> (Interval a -> Bool) -> f (Interval a) -> Maybe (f (Interval a))
forall (f :: * -> *) a.
(Monoid (f (Interval a)), Filterable f, IntervalAlgebraic a) =>
((Interval a -> Bool) -> f (Interval a) -> Bool)
-> (Interval a -> Bool) -> f (Interval a) -> Maybe (f (Interval a))
nothingIf (Interval a -> Bool) -> f (Interval a) -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any

-- | Returns the empty monoid structure if *all* of the element of input satisfy
--   the predicate condition
nothingIfAll :: (Monoid (f (Interval a)), Foldable f, Filterable f, IntervalAlgebraic a)=>
    (Interval a -> Bool) -- ^ predicate to apply to each element of input list
  -> f (Interval a)
  -> Maybe (f (Interval a))
nothingIfAll :: (Interval a -> Bool) -> f (Interval a) -> Maybe (f (Interval a))
nothingIfAll = ((Interval a -> Bool) -> f (Interval a) -> Bool)
-> (Interval a -> Bool) -> f (Interval a) -> Maybe (f (Interval a))
forall (f :: * -> *) a.
(Monoid (f (Interval a)), Filterable f, IntervalAlgebraic a) =>
((Interval a -> Bool) -> f (Interval a) -> Bool)
-> (Interval a -> Bool) -> f (Interval a) -> Maybe (f (Interval a))
nothingIf (Interval a -> Bool) -> f (Interval a) -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all


{- | 
Filter functions provides means for filtering 'Filterable' containers of 
@'Interval'@s based on @'IntervalAlgebraic'@ relations.
-}

-- |Creates a function for filtering a 'Witherable.Filterable' of @Interval a@s based on a predicate
filterMaker :: (Filterable f, IntervalAlgebraic a) =>
                 ComparativePredicateOf (Interval a)
                -> Interval a
                -> (f (Interval a) -> f (Interval a))
filterMaker :: ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
f Interval a
p = (Interval a -> Bool) -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a. Filterable f => (a -> Bool) -> f a -> f a
Witherable.filter (ComparativePredicateOf (Interval a)
`f` Interval a
p)

-- | Filter a 'Witherable.Filterable' of @Interval a@s to those that 'overlaps' the @Interval a@
--   in the first argument.
filterOverlaps :: (Filterable f, IntervalAlgebraic a) => 
                  Interval a -> f (Interval a) -> f (Interval a)
filterOverlaps :: Interval a -> f (Interval a) -> f (Interval a)
filterOverlaps = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
overlaps

-- | Filter a 'Witherable.Filterable' of @Interval a@s to those 'overlappedBy' the @Interval a@
--   in the first argument.
filterOverlappedBy :: (Filterable f, IntervalAlgebraic a) => 
                      Interval a -> f (Interval a) -> f (Interval a)
filterOverlappedBy :: Interval a -> f (Interval a) -> f (Interval a)
filterOverlappedBy = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
overlappedBy

-- | Filter a 'Witherable.Filterable' of Interval as to those 'before' the @Interval a@
--   in the first argument.
filterBefore :: (Filterable f, IntervalAlgebraic a) => 
                Interval a -> f (Interval a) -> f (Interval a)
filterBefore :: Interval a -> f (Interval a) -> f (Interval a)
filterBefore = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
before

-- | Filter a 'Witherable.Filterable' of Interval as to those 'after' the @Interval a@
--   in the first argument.
filterAfter :: (Filterable f, IntervalAlgebraic a) => 
               Interval a -> f (Interval a) -> f (Interval a)
filterAfter :: Interval a -> f (Interval a) -> f (Interval a)
filterAfter = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
after

-- | Filter a 'Witherable.Filterable' of Interval as to those 'starts' the @Interval a@
--   in the first argument.
filterStarts :: (Filterable f, IntervalAlgebraic a) => 
               Interval a -> f (Interval a) -> f (Interval a)
filterStarts :: Interval a -> f (Interval a) -> f (Interval a)
filterStarts = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
starts 

-- | Filter a 'Witherable.Filterable' of Interval as to those 'startedBy' the @Interval a@
--   in the first argument.
filterStartedBy :: (Filterable f, IntervalAlgebraic a) => 
               Interval a -> f (Interval a) -> f (Interval a)
filterStartedBy :: Interval a -> f (Interval a) -> f (Interval a)
filterStartedBy = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
startedBy 

-- | Filter a 'Witherable.Filterable' of Interval as to those 'finishes' the @Interval a@
--   in the first argument.
filterFinishes :: (Filterable f, IntervalAlgebraic a) => 
               Interval a -> f (Interval a) -> f (Interval a)
filterFinishes :: Interval a -> f (Interval a) -> f (Interval a)
filterFinishes = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
finishes

-- | Filter a 'Witherable.Filterable' of Interval as to those 'finishedBy' the @Interval a@
--   in the first argument.
filterFinishedBy :: (Filterable f, IntervalAlgebraic a) => 
               Interval a -> f (Interval a) -> f (Interval a)
filterFinishedBy :: Interval a -> f (Interval a) -> f (Interval a)
filterFinishedBy = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
finishedBy 

-- | Filter a 'Witherable.Filterable' of Interval as to those that 'meets' the @Interval a@
--   in the first argument.
filterMeets :: (Filterable f, IntervalAlgebraic a) => 
               Interval a -> f (Interval a) -> f (Interval a)
filterMeets :: Interval a -> f (Interval a) -> f (Interval a)
filterMeets = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
meets

-- | Filter a 'Witherable.Filterable' of Interval as to those 'metBy' the @Interval a@
--   in the first argument.
filterMetBy :: (Filterable f, IntervalAlgebraic a) => 
               Interval a -> f (Interval a) -> f (Interval a)
filterMetBy :: Interval a -> f (Interval a) -> f (Interval a)
filterMetBy = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
metBy

-- | Filter a 'Witherable.Filterable' of Interval as to those 'during' the @Interval a@
--   in the first argument.
filterDuring :: (Filterable f, IntervalAlgebraic a) => 
                Interval a -> f (Interval a) -> f (Interval a)
filterDuring :: Interval a -> f (Interval a) -> f (Interval a)
filterDuring = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
during

-- | Filter a 'Witherable.Filterable' of Interval as to those that 'contains'
--   the @Interval a@ in the first argument.
filterContains :: (Filterable f, IntervalAlgebraic a) => 
                  Interval a -> f (Interval a) -> f (Interval a)
filterContains :: Interval a -> f (Interval a) -> f (Interval a)
filterContains = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
contains

-- | Filter a 'Witherable.Filterable' of Interval as to those that 'equals'
--   the @Interval a@ in the first argument.
filterEquals :: (Filterable f, IntervalAlgebraic a) => 
                  Interval a -> f (Interval a) -> f (Interval a)
filterEquals :: Interval a -> f (Interval a) -> f (Interval a)
filterEquals = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
equals

-- | Filter a 'Witherable.Filterable' of Interval as to those that are 'disjoint'
--   from the @Interval a@ in the first argument.
filterDisjoint :: (Filterable f, IntervalAlgebraic a) => 
                  Interval a -> f (Interval a) -> f (Interval a)
filterDisjoint :: Interval a -> f (Interval a) -> f (Interval a)
filterDisjoint = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
disjoint

-- | Filter a 'Witherable.Filterable' of Interval as to those that are 'notDisjoint'
--   from the @Interval a@ in the first argument.
filterNotDisjoint :: (Filterable f, IntervalAlgebraic a) => 
                     Interval a -> f (Interval a) -> f (Interval a)
filterNotDisjoint :: Interval a -> f (Interval a) -> f (Interval a)
filterNotDisjoint = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
notDisjoint

-- | Filter a 'Witherable.Filterable' of Interval as to those that are 'within'
--   the @Interval a@ in the first argument.
filterWithin :: (Filterable f, IntervalAlgebraic a) => 
                Interval a -> f (Interval a) -> f (Interval a)
filterWithin :: Interval a -> f (Interval a) -> f (Interval a)
filterWithin = ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
forall (f :: * -> *) a.
(Filterable f, IntervalAlgebraic a) =>
ComparativePredicateOf (Interval a)
-> Interval a -> f (Interval a) -> f (Interval a)
filterMaker ComparativePredicateOf (Interval a)
forall a.
IntervalAlgebraic a =>
ComparativePredicateOf (Interval a)
disjoint