{-# LANGUAGE RankNTypes, ScopedTypeVariables, TypeApplications #-}
module Build.Task.Monad (track, trackM, isInput, compute, partial, exceptional) where
import Control.Monad.Trans
import Control.Monad.Trans.Except
import Control.Monad.Trans.Maybe
import Control.Monad.Writer
import Data.Functor.Identity
import Data.Maybe
import Build.Task
track :: Task Monad k v -> (k -> v) -> (v, [k])
track task fetch = runWriter $ task (\k -> writer (fetch k, [k]))
trackM :: forall m k v. Monad m => Task Monad k v -> (k -> m v) -> m (v, [k])
trackM task fetch = runWriterT $ task trackingFetch
where
trackingFetch :: k -> WriterT [k] m v
trackingFetch k = tell [k] >> lift (fetch k)
isInput :: forall k v. Tasks Monad k v -> k -> Bool
isInput tasks key = isNothing (tasks key :: Maybe ((k -> Maybe v) -> Maybe v))
compute :: Task Monad k v -> (k -> v) -> v
compute task store = runIdentity $ task (Identity . store)
partial :: Task Monad k v -> Task Monad k (Maybe v)
partial task fetch = runMaybeT $ task (MaybeT . fetch)
exceptional :: Task Monad k v -> Task Monad k (Either e v)
exceptional task fetch = runExceptT $ task (ExceptT . fetch)