{-|
Module      : Cohort Index 
Description : Defines the Index and related types and functions
Copyright   : (c) NoviSci, Inc 2020
License     : BSD3
Maintainer  : bsaul@novisci.com
-}

{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
-- {-# LANGUAGE Safe #-}

module Cohort.AssessmentIntervals
  (
  {- |
The assessment intervals provided are:

* 'Baseline': an interval which either 'IntervalAlgebra.meets' or
  'IntervalAlgebra.precedes' index. Covariates are typically assessed during
  baseline intervals. A cohort's specification may include multiple baseline
  intervals, as different features may require different baseline intervals.
  For example, one feature may use a baseline interval of 365 days prior to
  index, while another uses a baseline interval of 90 days before index up
  to 30 days before index.
* `Followup`: an interval which is 'IntervalAlgebra.startedBy', 
  'IntervalAlgebra.metBy', or 'IntervalAlgebra.after' an 'Index'. Outcomes
  are typically assessed during followup intervals. Similar to 'Baseline',
    a cohort's specification may include multiple followup intervals, 
    as different features may require different followup intervals. 

In future versions, one subject may have multiple values for an 'Index'
corresponding to unique 'Cohort.Core.ObsUnit'. That is, there is a 1-to-1 map between 
index values and observational units, but there may be a 1-to-many map from 
subjects to indices.

While users are protected from forming invalid assessment intervals, they still
need to carefully consider how to filter events based on the assessment interval. 
Consider the following data:

@
               _      <- Index    (15, 16)
     ----------       <- Baseline (5, 15)
 ---                  <- A (1, 4)
  ---                 <- B (2, 5)
    ---               <- C (4, 7)
      ---             <- D (5, 8)
         ---          <- E (8, 11)
            ---       <- F (12, 15)
              ---     <- G (14, 17)
                 ___  <- H (17, 20)
|----|----|----|----|
0         10        20
@

We have index, baseline, and 8 events (A-H). If Baseline is our assessment interval,
then the events concuring (i.e. not disjoint) with Baseline are C-G.  While C-F
probably make sense to use in deriving some covariate, what about G? The event G
begins during baseline but ends after index. If you want, for example, to know
how many events started during baseline, then you’d want to include G in your
filter (using 'IntervalAlgebra.concur'). But if you wanted to know the durations 
of events enclosed by baseline, then you wouldn’t want to filter using concur 
and instead perhaps use 'IntervalAlgebra.enclosedBy'.


    -}
    BaselineInterval
  , Baseline(..)
  , FollowupInterval
  , Followup(..)
  , AssessmentInterval
  , makeBaselineFromIndex
  , makeBaselineBeforeIndex
  , makeFollowupFromIndex
  , makeFollowupMeetingIndex
  , makeFollowupAfterIndex
  ) where

import           Cohort.Index                   ( Index )
import           Data.Eq                        ( Eq )
import           Data.Function                  ( ($) )
import           Data.Functor                   ( Functor(fmap) )
import           Data.Ord                       ( (<=)
                                                , Ord
                                                )
import           GHC.Generics                   ( Generic )
import           GHC.Num                        ( Num((+)) )
import           GHC.Show                       ( Show )
import           IntervalAlgebra                ( Interval
                                                , IntervalSizeable(..)
                                                , Intervallic(..)
                                                , begin
                                                , beginerval
                                                , duration
                                                , end
                                                , enderval
                                                )

{-| A type to contain baseline intervals. See the 'Baseline' typeclass for methods
to create values of this type.
-}
newtype BaselineInterval a = MkBaselineInterval (Interval a)
  deriving (BaselineInterval a -> BaselineInterval a -> Bool
(BaselineInterval a -> BaselineInterval a -> Bool)
-> (BaselineInterval a -> BaselineInterval a -> Bool)
-> Eq (BaselineInterval a)
forall a. Eq a => BaselineInterval a -> BaselineInterval a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BaselineInterval a -> BaselineInterval a -> Bool
$c/= :: forall a. Eq a => BaselineInterval a -> BaselineInterval a -> Bool
== :: BaselineInterval a -> BaselineInterval a -> Bool
$c== :: forall a. Eq a => BaselineInterval a -> BaselineInterval a -> Bool
Eq, Int -> BaselineInterval a -> ShowS
[BaselineInterval a] -> ShowS
BaselineInterval a -> String
(Int -> BaselineInterval a -> ShowS)
-> (BaselineInterval a -> String)
-> ([BaselineInterval a] -> ShowS)
-> Show (BaselineInterval a)
forall a. (Show a, Ord a) => Int -> BaselineInterval a -> ShowS
forall a. (Show a, Ord a) => [BaselineInterval a] -> ShowS
forall a. (Show a, Ord a) => BaselineInterval a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BaselineInterval a] -> ShowS
$cshowList :: forall a. (Show a, Ord a) => [BaselineInterval a] -> ShowS
show :: BaselineInterval a -> String
$cshow :: forall a. (Show a, Ord a) => BaselineInterval a -> String
showsPrec :: Int -> BaselineInterval a -> ShowS
$cshowsPrec :: forall a. (Show a, Ord a) => Int -> BaselineInterval a -> ShowS
Show, (forall x. BaselineInterval a -> Rep (BaselineInterval a) x)
-> (forall x. Rep (BaselineInterval a) x -> BaselineInterval a)
-> Generic (BaselineInterval a)
forall x. Rep (BaselineInterval a) x -> BaselineInterval a
forall x. BaselineInterval a -> Rep (BaselineInterval a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (BaselineInterval a) x -> BaselineInterval a
forall a x. BaselineInterval a -> Rep (BaselineInterval a) x
$cto :: forall a x. Rep (BaselineInterval a) x -> BaselineInterval a
$cfrom :: forall a x. BaselineInterval a -> Rep (BaselineInterval a) x
Generic)

instance Functor BaselineInterval where
  fmap :: (a -> b) -> BaselineInterval a -> BaselineInterval b
fmap a -> b
f (MkBaselineInterval Interval a
x) = Interval b -> BaselineInterval b
forall a. Interval a -> BaselineInterval a
MkBaselineInterval ((a -> b) -> Interval a -> Interval b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Interval a
x)

instance (Ord a) => Intervallic BaselineInterval a where
  getInterval :: BaselineInterval a -> Interval a
getInterval (MkBaselineInterval Interval a
x) = Interval a -> Interval a
forall (i :: * -> *) a. Intervallic i a => i a -> Interval a
getInterval Interval a
x
  setInterval :: BaselineInterval a -> Interval a -> BaselineInterval a
setInterval (MkBaselineInterval Interval a
x) Interval a
y = Interval a -> BaselineInterval a
forall a. Interval a -> BaselineInterval a
MkBaselineInterval (Interval a -> Interval a -> Interval a
forall (i :: * -> *) a. Intervallic i a => i a -> Interval a -> i a
setInterval Interval a
x Interval a
y)

{-| 
Provides functions for creating a 'BaselineInterval' from an 'Index'. The 
'baseline' function should satify:

[Meets]

  @'IntervalAlgebra.relate' ('baseline' d i) i = 'IntervalAlgebra.Meets'@

The 'baselineBefore' function should satisfy:

[Before]
  
  @'IntervalAlgebra.relate' ('baselineBefore' s d i) i = 'IntervalAlgebra.Before'@

>>> import Cohort.Index
>>> import IntervalAlgebra
>>> x = makeIndex (beginerval 1 10)
>>> b =baseline 10 x
>>> b
>>> relate b x
MkBaselineInterval (0, 10)
Meets

>>> import Cohort.Index
>>> import IntervalAlgebra
>>> x = makeIndex (beginerval 1 10)
>>> b = baselineBefore 2 4 x
>>> b
>>> relate b x
MkBaselineInterval (4, 8)
Before
-}
class Intervallic i a => Baseline i a where
  -- | Creates a 'BaselineInterval' of the given duration that 'IntervalAlgebra.Meets'
  -- the 'Index' interval.
  baseline ::
    ( IntervalSizeable a b) =>
      b -- ^ duration of baseline
    -> Index i a -- ^ the 'Index' event
    -> BaselineInterval a
  baseline b
dur Index i a
index = Interval a -> BaselineInterval a
forall a. Interval a -> BaselineInterval a
MkBaselineInterval (b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
enderval b
dur (Index i a -> a
forall (i :: * -> *) a. Intervallic i a => i a -> a
begin Index i a
index))

  -- | Creates a 'BaselineInterval' of the given duration that 'IntervalAlgebra.precedes'
  -- the 'Index' interval. 
  baselineBefore ::
    ( IntervalSizeable a b) =>
       b -- ^ duration to shift back 
    -> b -- ^ duration of baseline
    -> Index i a -- ^ the 'Index' event
    -> BaselineInterval a
  baselineBefore b
shiftBy b
dur Index i a
index =
    Interval a -> BaselineInterval a
forall a. Interval a -> BaselineInterval a
MkBaselineInterval (Interval a -> BaselineInterval a)
-> Interval a -> BaselineInterval a
forall a b. (a -> b) -> a -> b
$ b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
enderval b
dur (Interval a -> a
forall (i :: * -> *) a. Intervallic i a => i a -> a
begin (b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
enderval b
shiftBy (Index i a -> a
forall (i :: * -> *) a. Intervallic i a => i a -> a
begin Index i a
index)))

instance (Ord a) => Baseline Interval a

{-| A type to contain followup intervals. See the 'Followup' typeclass for methods
to create values of this type.
-}
newtype FollowupInterval a = MkFollowupInterval (Interval a)
  deriving (FollowupInterval a -> FollowupInterval a -> Bool
(FollowupInterval a -> FollowupInterval a -> Bool)
-> (FollowupInterval a -> FollowupInterval a -> Bool)
-> Eq (FollowupInterval a)
forall a. Eq a => FollowupInterval a -> FollowupInterval a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FollowupInterval a -> FollowupInterval a -> Bool
$c/= :: forall a. Eq a => FollowupInterval a -> FollowupInterval a -> Bool
== :: FollowupInterval a -> FollowupInterval a -> Bool
$c== :: forall a. Eq a => FollowupInterval a -> FollowupInterval a -> Bool
Eq, Int -> FollowupInterval a -> ShowS
[FollowupInterval a] -> ShowS
FollowupInterval a -> String
(Int -> FollowupInterval a -> ShowS)
-> (FollowupInterval a -> String)
-> ([FollowupInterval a] -> ShowS)
-> Show (FollowupInterval a)
forall a. (Show a, Ord a) => Int -> FollowupInterval a -> ShowS
forall a. (Show a, Ord a) => [FollowupInterval a] -> ShowS
forall a. (Show a, Ord a) => FollowupInterval a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FollowupInterval a] -> ShowS
$cshowList :: forall a. (Show a, Ord a) => [FollowupInterval a] -> ShowS
show :: FollowupInterval a -> String
$cshow :: forall a. (Show a, Ord a) => FollowupInterval a -> String
showsPrec :: Int -> FollowupInterval a -> ShowS
$cshowsPrec :: forall a. (Show a, Ord a) => Int -> FollowupInterval a -> ShowS
Show, (forall x. FollowupInterval a -> Rep (FollowupInterval a) x)
-> (forall x. Rep (FollowupInterval a) x -> FollowupInterval a)
-> Generic (FollowupInterval a)
forall x. Rep (FollowupInterval a) x -> FollowupInterval a
forall x. FollowupInterval a -> Rep (FollowupInterval a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (FollowupInterval a) x -> FollowupInterval a
forall a x. FollowupInterval a -> Rep (FollowupInterval a) x
$cto :: forall a x. Rep (FollowupInterval a) x -> FollowupInterval a
$cfrom :: forall a x. FollowupInterval a -> Rep (FollowupInterval a) x
Generic)

instance Functor FollowupInterval where
  fmap :: (a -> b) -> FollowupInterval a -> FollowupInterval b
fmap a -> b
f (MkFollowupInterval Interval a
x) = Interval b -> FollowupInterval b
forall a. Interval a -> FollowupInterval a
MkFollowupInterval ((a -> b) -> Interval a -> Interval b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Interval a
x)

instance (Ord a) => Intervallic FollowupInterval a where
  getInterval :: FollowupInterval a -> Interval a
getInterval (MkFollowupInterval Interval a
x) = Interval a -> Interval a
forall (i :: * -> *) a. Intervallic i a => i a -> Interval a
getInterval Interval a
x
  setInterval :: FollowupInterval a -> Interval a -> FollowupInterval a
setInterval (MkFollowupInterval Interval a
x) Interval a
y = Interval a -> FollowupInterval a
forall a. Interval a -> FollowupInterval a
MkFollowupInterval (Interval a -> Interval a -> Interval a
forall (i :: * -> *) a. Intervallic i a => i a -> Interval a -> i a
setInterval Interval a
x Interval a
y)

{-| 
Provides functions for creating a 'FollowupInterval' from an 'Index'. The 
'followup' function should satify:

[StartedBy]

  @'IntervalAlgebra.relate' ('followup' d i) i = 'IntervalAlgebra.StartedBy'@

The 'followupMetBy' function should satisfy:

[MetBy]
  
  @'IntervalAlgebra.relate' ('followupMetBy' d i) i = 'IntervalAlgebra.MetBy'@

The 'followupAfter' function should satisfy:

[After]

  @'IntervalAlgebra.relate' ('followupAfter' s d i) i = 'IntervalAlgebra.After'@

>>> import Cohort.Index
>>> import IntervalAlgebra
>>> x = makeIndex (beginerval 1 10)
>>> f = followup 10 x
>>> f
>>> relate f x
MkFollowupInterval (10, 20)
StartedBy

Note the consequence of providing a duration less than or equal to the duration 
of the index: a 'IntervalAlgebra.moment' is added to the duration, so that the 
end of the 'FollowupInterval' is greater than the end of the 'Index'.

>>> import Cohort.Index
>>> import IntervalAlgebra
>>> x = makeIndex (beginerval 1 10)
>>> f = followup 1 x
>>> f
>>> relate f x
MkFollowupInterval (10, 12)
StartedBy

>>> import Cohort.Index
>>> import IntervalAlgebra
>>> x = makeIndex (beginerval 1 10)
>>> f = followupMetBy 9 x
>>> f
>>> relate f x
MkFollowupInterval (11, 20)
MetBy

>>> import Cohort.Index
>>> import IntervalAlgebra
>>> x = makeIndex (beginerval 1 10)
>>> f = followupAfter 1 9 x
>>> f
>>> relate f x
MkFollowupInterval (12, 21)
After
-}
class Intervallic i a => Followup i a where
  followup ::
    ( IntervalSizeable a b
    , Intervallic i a) =>
      b -- ^ duration of followup
    -> Index i a -- ^ the 'Index' event
    -> FollowupInterval a
  followup b
dur Index i a
index = Interval a -> FollowupInterval a
forall a. Interval a -> FollowupInterval a
MkFollowupInterval (b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
beginerval b
d2 (Index i a -> a
forall (i :: * -> *) a. Intervallic i a => i a -> a
begin Index i a
index))
    where d2 :: b
d2 = if b
dur b -> b -> Bool
forall a. Ord a => a -> a -> Bool
<= Index i a -> b
forall a b (i :: * -> *).
(IntervalSizeable a b, Intervallic i a) =>
i a -> b
duration Index i a
index
                 then Index i a -> b
forall a b (i :: * -> *).
(IntervalSizeable a b, Intervallic i a) =>
i a -> b
duration Index i a
index b -> b -> b
forall a. Num a => a -> a -> a
+ Index i a -> b
forall a b (i :: * -> *).
(IntervalSizeable a b, Intervallic i a) =>
i a -> b
moment' Index i a
index
                 else b
dur

  followupMetBy ::
    ( IntervalSizeable a b
    , Intervallic i a) =>
      b -- ^ duration of followup
    -> Index i a -- ^ the 'Index' event
    -> FollowupInterval a
  followupMetBy b
dur Index i a
index = Interval a -> FollowupInterval a
forall a. Interval a -> FollowupInterval a
MkFollowupInterval (b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
beginerval b
dur (Index i a -> a
forall (i :: * -> *) a. Intervallic i a => i a -> a
end Index i a
index))

  followupAfter ::
    ( IntervalSizeable a b
    , Intervallic i a) =>
       b -- ^ duration add between the end of index and begin of followup
    -> b -- ^ duration of followup
    -> Index i a -- ^ the 'Index' event
    -> FollowupInterval a
  followupAfter b
shiftBy b
dur Index i a
index =
    Interval a -> FollowupInterval a
forall a. Interval a -> FollowupInterval a
MkFollowupInterval (Interval a -> FollowupInterval a)
-> Interval a -> FollowupInterval a
forall a b. (a -> b) -> a -> b
$ b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
beginerval b
dur (Interval a -> a
forall (i :: * -> *) a. Intervallic i a => i a -> a
end (b -> a -> Interval a
forall a b. IntervalSizeable a b => b -> a -> Interval a
beginerval b
shiftBy (Index i a -> a
forall (i :: * -> *) a. Intervallic i a => i a -> a
end Index i a
index)))

instance (Ord a) => Followup Interval a

-- | A data type that contains variants of intervals during which assessment
-- may occur.
data AssessmentInterval a =
      Bl (BaselineInterval a) -- ^ holds a 'BaselineInterval'
    | Fl (FollowupInterval a) -- ^ holds a 'FollowupInterval'
    deriving (AssessmentInterval a -> AssessmentInterval a -> Bool
(AssessmentInterval a -> AssessmentInterval a -> Bool)
-> (AssessmentInterval a -> AssessmentInterval a -> Bool)
-> Eq (AssessmentInterval a)
forall a.
Eq a =>
AssessmentInterval a -> AssessmentInterval a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AssessmentInterval a -> AssessmentInterval a -> Bool
$c/= :: forall a.
Eq a =>
AssessmentInterval a -> AssessmentInterval a -> Bool
== :: AssessmentInterval a -> AssessmentInterval a -> Bool
$c== :: forall a.
Eq a =>
AssessmentInterval a -> AssessmentInterval a -> Bool
Eq, Int -> AssessmentInterval a -> ShowS
[AssessmentInterval a] -> ShowS
AssessmentInterval a -> String
(Int -> AssessmentInterval a -> ShowS)
-> (AssessmentInterval a -> String)
-> ([AssessmentInterval a] -> ShowS)
-> Show (AssessmentInterval a)
forall a. (Show a, Ord a) => Int -> AssessmentInterval a -> ShowS
forall a. (Show a, Ord a) => [AssessmentInterval a] -> ShowS
forall a. (Show a, Ord a) => AssessmentInterval a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AssessmentInterval a] -> ShowS
$cshowList :: forall a. (Show a, Ord a) => [AssessmentInterval a] -> ShowS
show :: AssessmentInterval a -> String
$cshow :: forall a. (Show a, Ord a) => AssessmentInterval a -> String
showsPrec :: Int -> AssessmentInterval a -> ShowS
$cshowsPrec :: forall a. (Show a, Ord a) => Int -> AssessmentInterval a -> ShowS
Show, (forall x. AssessmentInterval a -> Rep (AssessmentInterval a) x)
-> (forall x. Rep (AssessmentInterval a) x -> AssessmentInterval a)
-> Generic (AssessmentInterval a)
forall x. Rep (AssessmentInterval a) x -> AssessmentInterval a
forall x. AssessmentInterval a -> Rep (AssessmentInterval a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (AssessmentInterval a) x -> AssessmentInterval a
forall a x. AssessmentInterval a -> Rep (AssessmentInterval a) x
$cto :: forall a x. Rep (AssessmentInterval a) x -> AssessmentInterval a
$cfrom :: forall a x. AssessmentInterval a -> Rep (AssessmentInterval a) x
Generic)

instance (Ord a) => Intervallic AssessmentInterval a where
  getInterval :: AssessmentInterval a -> Interval a
getInterval (Bl BaselineInterval a
x) = BaselineInterval a -> Interval a
forall (i :: * -> *) a. Intervallic i a => i a -> Interval a
getInterval BaselineInterval a
x
  getInterval (Fl FollowupInterval a
x) = FollowupInterval a -> Interval a
forall (i :: * -> *) a. Intervallic i a => i a -> Interval a
getInterval FollowupInterval a
x

  setInterval :: AssessmentInterval a -> Interval a -> AssessmentInterval a
setInterval (Bl BaselineInterval a
x) Interval a
y = BaselineInterval a -> AssessmentInterval a
forall a. BaselineInterval a -> AssessmentInterval a
Bl (BaselineInterval a -> Interval a -> BaselineInterval a
forall (i :: * -> *) a. Intervallic i a => i a -> Interval a -> i a
setInterval BaselineInterval a
x Interval a
y)
  setInterval (Fl FollowupInterval a
x) Interval a
y = FollowupInterval a -> AssessmentInterval a
forall a. FollowupInterval a -> AssessmentInterval a
Fl (FollowupInterval a -> Interval a -> FollowupInterval a
forall (i :: * -> *) a. Intervallic i a => i a -> Interval a -> i a
setInterval FollowupInterval a
x Interval a
y)

instance Functor AssessmentInterval where
  fmap :: (a -> b) -> AssessmentInterval a -> AssessmentInterval b
fmap a -> b
f (Bl BaselineInterval a
x) = BaselineInterval b -> AssessmentInterval b
forall a. BaselineInterval a -> AssessmentInterval a
Bl ((a -> b) -> BaselineInterval a -> BaselineInterval b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f BaselineInterval a
x)
  fmap a -> b
f (Fl FollowupInterval a
x) = FollowupInterval b -> AssessmentInterval b
forall a. FollowupInterval a -> AssessmentInterval a
Fl ((a -> b) -> FollowupInterval a -> FollowupInterval b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f FollowupInterval a
x)

-- | Creates an 'AssessmentInterval' using the 'baseline' function. 
-- 
-- >>> import Cohort.Index
-- >>> x = makeIndex $ beginerval 1 10
-- >>> makeBaselineFromIndex 10 x
-- Bl (MkBaselineInterval (0, 10))
--
makeBaselineFromIndex
  :: (Baseline i a, IntervalSizeable a b)
  => b
  -> Index i a
  -> AssessmentInterval a
makeBaselineFromIndex :: b -> Index i a -> AssessmentInterval a
makeBaselineFromIndex b
dur Index i a
index = BaselineInterval a -> AssessmentInterval a
forall a. BaselineInterval a -> AssessmentInterval a
Bl (b -> Index i a -> BaselineInterval a
forall (i :: * -> *) a b.
(Baseline i a, IntervalSizeable a b) =>
b -> Index i a -> BaselineInterval a
baseline b
dur Index i a
index)

-- | Creates an 'AssessmentInterval' using the 'baselineBefore' function. 
-- 
-- >>> import Cohort.Index
-- >>> x = makeIndex $ beginerval 1 10
-- >>> makeBaselineBeforeIndex 2 10 x
-- Bl (MkBaselineInterval (-2, 8))
--
makeBaselineBeforeIndex
  :: (Baseline i a, IntervalSizeable a b)
  => b
  -> b
  -> Index i a
  -> AssessmentInterval a
makeBaselineBeforeIndex :: b -> b -> Index i a -> AssessmentInterval a
makeBaselineBeforeIndex b
shiftBy b
dur Index i a
index =
  BaselineInterval a -> AssessmentInterval a
forall a. BaselineInterval a -> AssessmentInterval a
Bl (b -> b -> Index i a -> BaselineInterval a
forall (i :: * -> *) a b.
(Baseline i a, IntervalSizeable a b) =>
b -> b -> Index i a -> BaselineInterval a
baselineBefore b
shiftBy b
dur Index i a
index)

-- | Creates an 'AssessmentInterval' using the 'followup' function. 
-- 
-- >>> import Cohort.Index
-- >>> x = makeIndex $ beginerval 1 10
-- >>> makeFollowupFromIndex 10 x
-- Fl (MkFollowupInterval (10, 20))
--
makeFollowupFromIndex
  :: (Followup i a, IntervalSizeable a b)
  => b
  -> Index i a
  -> AssessmentInterval a
makeFollowupFromIndex :: b -> Index i a -> AssessmentInterval a
makeFollowupFromIndex b
dur Index i a
index = FollowupInterval a -> AssessmentInterval a
forall a. FollowupInterval a -> AssessmentInterval a
Fl (b -> Index i a -> FollowupInterval a
forall (i :: * -> *) a b.
(Followup i a, IntervalSizeable a b, Intervallic i a) =>
b -> Index i a -> FollowupInterval a
followup b
dur Index i a
index)

-- | Creates an 'AssessmentInterval' using the 'followupMetBy' function. 
-- 
-- >>> import Cohort.Index
-- >>> x = makeIndex $ beginerval 1 10
-- >>> makeFollowupMeetingIndex 10 x
-- Fl (MkFollowupInterval (11, 21))
--
makeFollowupMeetingIndex
  :: (Followup i a, IntervalSizeable a b)
  => b
  -> Index i a
  -> AssessmentInterval a
makeFollowupMeetingIndex :: b -> Index i a -> AssessmentInterval a
makeFollowupMeetingIndex b
dur Index i a
index = FollowupInterval a -> AssessmentInterval a
forall a. FollowupInterval a -> AssessmentInterval a
Fl (b -> Index i a -> FollowupInterval a
forall (i :: * -> *) a b.
(Followup i a, IntervalSizeable a b, Intervallic i a) =>
b -> Index i a -> FollowupInterval a
followupMetBy b
dur Index i a
index)

-- | Creates an 'AssessmentInterval' using the 'followupAfter' function. 
-- 
-- >>> import Cohort.Index
-- >>> x = makeIndex $ beginerval 1 10
-- >>> makeFollowupAfterIndex 10 10 x
-- Fl (MkFollowupInterval (21, 31))
--
makeFollowupAfterIndex
  :: (Followup i a, IntervalSizeable a b)
  => b
  -> b
  -> Index i a
  -> AssessmentInterval a
makeFollowupAfterIndex :: b -> b -> Index i a -> AssessmentInterval a
makeFollowupAfterIndex b
shiftBy b
dur Index i a
index = FollowupInterval a -> AssessmentInterval a
forall a. FollowupInterval a -> AssessmentInterval a
Fl (b -> b -> Index i a -> FollowupInterval a
forall (i :: * -> *) a b.
(Followup i a, IntervalSizeable a b, Intervallic i a) =>
b -> b -> Index i a -> FollowupInterval a
followupAfter b
shiftBy b
dur Index i a
index)