{-|
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.Index
  (
  {- |
    An 'Index' is an interval of time from which the assessment intervals for an
   observational unit may be derived. Assessment intervals (encoded in the type
   'Cohort.AssessmentInterval') are intervals of time during which features are evaluated. 
   -}
    Index
  , makeIndex
  ) where

import           Data.Aeson                     ( ToJSON )
import           Data.Eq                        ( Eq )
import           Data.Functor                   ( Functor(fmap) )
import           Data.Ord                       ( Ord )
import           GHC.Generics                   ( Generic )
import           GHC.Show                       ( Show )
import           IntervalAlgebra                ( Interval
                                                , Intervallic(..)
                                                )

{-|
An @Index@ is a wrapper for an @Intervallic@ used to indicate that a particular
interval is considered an index interval to which other intervals will be compared.
-}
newtype Index i a = MkIndex {
    Index i a -> i a
getIndex :: i a -- ^ Unwrap an @Index@
  } deriving (Index i a -> Index i a -> Bool
(Index i a -> Index i a -> Bool)
-> (Index i a -> Index i a -> Bool) -> Eq (Index i a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (i :: * -> *) a. Eq (i a) => Index i a -> Index i a -> Bool
/= :: Index i a -> Index i a -> Bool
$c/= :: forall (i :: * -> *) a. Eq (i a) => Index i a -> Index i a -> Bool
== :: Index i a -> Index i a -> Bool
$c== :: forall (i :: * -> *) a. Eq (i a) => Index i a -> Index i a -> Bool
Eq, Int -> Index i a -> ShowS
[Index i a] -> ShowS
Index i a -> String
(Int -> Index i a -> ShowS)
-> (Index i a -> String)
-> ([Index i a] -> ShowS)
-> Show (Index i a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (i :: * -> *) a. Show (i a) => Int -> Index i a -> ShowS
forall (i :: * -> *) a. Show (i a) => [Index i a] -> ShowS
forall (i :: * -> *) a. Show (i a) => Index i a -> String
showList :: [Index i a] -> ShowS
$cshowList :: forall (i :: * -> *) a. Show (i a) => [Index i a] -> ShowS
show :: Index i a -> String
$cshow :: forall (i :: * -> *) a. Show (i a) => Index i a -> String
showsPrec :: Int -> Index i a -> ShowS
$cshowsPrec :: forall (i :: * -> *) a. Show (i a) => Int -> Index i a -> ShowS
Show, (forall x. Index i a -> Rep (Index i a) x)
-> (forall x. Rep (Index i a) x -> Index i a)
-> Generic (Index i a)
forall x. Rep (Index i a) x -> Index i a
forall x. Index i a -> Rep (Index i a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (i :: * -> *) a x. Rep (Index i a) x -> Index i a
forall (i :: * -> *) a x. Index i a -> Rep (Index i a) x
$cto :: forall (i :: * -> *) a x. Rep (Index i a) x -> Index i a
$cfrom :: forall (i :: * -> *) a x. Index i a -> Rep (Index i a) x
Generic)

-- | Creates a new @'Index'@.
makeIndex :: Intervallic i a => i a -> Index i a
makeIndex :: i a -> Index i a
makeIndex = i a -> Index i a
forall (i :: * -> *) a. i a -> Index i a
MkIndex

instance (Functor i) => Functor (Index i) where
  fmap :: (a -> b) -> Index i a -> Index i b
fmap a -> b
f (MkIndex i a
x) = i b -> Index i b
forall (i :: * -> *) a. i a -> Index i a
MkIndex ((a -> b) -> i a -> i b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f i a
x)

instance (Intervallic i a) => Intervallic (Index i) a where
  getInterval :: Index i a -> Interval a
getInterval (MkIndex i a
x) = i a -> Interval a
forall (i :: * -> *) a. Intervallic i a => i a -> Interval a
getInterval i a
x
  setInterval :: Index i a -> Interval a -> Index i a
setInterval (MkIndex i a
x) Interval a
y = i a -> Index i a
forall (i :: * -> *) a. i a -> Index i a
MkIndex (i a -> Interval a -> i a
forall (i :: * -> *) a. Intervallic i a => i a -> Interval a -> i a
setInterval i a
x Interval a
y)

instance (Intervallic i a, ToJSON (i a)) => ToJSON (Index i a)