-- | 
-- Module      : Data.Allen 
-- Description : Main module for Allen's interval algebra. 
-- Maintainer  : Archaversine
--
-- This module provides a monad for computing with Allen's interval algebra. 
-- The monad keeps track of the interval graph that is being built up during 
-- the computation. The interval graph is represented as a map from interval 
-- identifiers to intervals. 
--
-- = Intervals
-- Intervals can be created using the 'interval' function:
--
-- @ 
-- calc :: 'Allen' ()
-- calc = do 
--   sleeps <- 'interval'
--   snores <- 'interval'
--   wakeup <- 'interval'
--   ...
-- @ 
--
-- == Retrieving interval data
-- Most functions perform operations on intervals solely with the use of their 
-- IDs. However, sometimes it is useful to retrieve the actual interval data. 
-- To get the actual interval data, use the 'fromID' function:
--
-- @ 
-- calc :: Allen () 
-- calc = do 
--   sleeps         <- 'interval' 
--   sleepsInterval <- 'fromID' sleeps
--   ...
-- @
--
-- Note that in the above example, updating the interval @sleeps@ will not 
-- update the interval @sleepsInterval@.
--
-- == Combining calculations
-- Sometimes, it is useful to define a set of intervals in one place and use 
-- then repeatedly in other places. Here is an example that reuses the intervals 
-- @a@ and @b@:
--
-- @ 
-- network :: 'Allen' ('IntervalID', 'IntervalID')
-- network = do 
--   a <- 'interval' 
--   b <- 'interval' 
--
--   'assume' a 'During' b 
--
--   return (a, b)
--
-- calc1 :: 'Allen' () 
-- calc1 = do 
--   (a, b) <- network 
--   c      <- 'interval'
--
--   'assume' a 'Precedes' c
--   ...
--
-- calc2 :: 'Allen' ()
-- calc2 = do 
--   (a, b) <- network 
--   c      <- 'interval'
--
--   'assume' a 'Contains' c
--   ...
-- @
--
--  = Relations 
-- Intervals can have relations with one another. For example, in the above 
-- example a valid relation would be that one sleeps during snores. Adding  
-- relations is done using one of the assume functions:
--
-- @ 
-- calc :: Allen () 
-- calc = do 
--    sleeps <- 'interval'
--    snores <- 'interval'
--    wakeup <- 'interval'
--
--    'assume' snores 'During' sleeps
--    'assume' wakeup 'PrecededBy' sleeps
-- @
--
-- Sometimes, intervals have more than one possible relation with one another.
-- For example, snores is 'During' sleeps, but it could also be 'StartedBy' sleeps, 
-- or it could 'Equals' sleeps. In such cases, the 'assumeSet' function can be 
-- used: 
--
-- @  
-- calc :: 'Allen' () 
-- calc = do 
--    sleeps <- 'interval'
--    snores <- 'interval'
--    wakeup <- 'interval'
--
--    'assumeSet' snores ['During', 'StartedBy', 'Equals'] sleeps
-- @
--
-- There are thirteen different relations intervals can have with each other. 
-- They are identified with the 'Relation' type.

module Data.Allen ( module Data.Allen.Types 
                  , module Data.Allen.Interval
                  , module Data.Allen.Relation
                  , execAllen
                  , evalAllen
                  , runAllen
                  ) where

import Control.Monad.State

import Data.Allen.Types
import Data.Allen.Interval
import Data.Allen.Relation

import qualified Data.Map.Strict as Map

-- | Return the resulting interval graph of an allen computation
execAllen :: Allen a -> IntervalGraph
execAllen :: forall a. Allen a -> IntervalGraph
execAllen = (a, IntervalGraph) -> IntervalGraph
forall a b. (a, b) -> b
snd ((a, IntervalGraph) -> IntervalGraph)
-> (Allen a -> (a, IntervalGraph)) -> Allen a -> IntervalGraph
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Allen a -> (a, IntervalGraph)
forall a. Allen a -> (a, IntervalGraph)
runAllen

-- | Return the result of an allen computation
evalAllen :: Allen a -> a
evalAllen :: forall a. Allen a -> a
evalAllen = (a, IntervalGraph) -> a
forall a b. (a, b) -> a
fst ((a, IntervalGraph) -> a)
-> (Allen a -> (a, IntervalGraph)) -> Allen a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Allen a -> (a, IntervalGraph)
forall a. Allen a -> (a, IntervalGraph)
runAllen

-- | Return the result of an allen computation and the resulting interval graph
runAllen :: Allen a -> (a, IntervalGraph)
runAllen :: forall a. Allen a -> (a, IntervalGraph)
runAllen = (Allen a -> IntervalGraph -> (a, IntervalGraph))
-> IntervalGraph -> Allen a -> (a, IntervalGraph)
forall a b c. (a -> b -> c) -> b -> a -> c
flip Allen a -> IntervalGraph -> (a, IntervalGraph)
forall s a. State s a -> s -> (a, s)
runState IntervalGraph
forall k a. Map k a
Map.empty