build-1.1: src/Build/SelfTracking/Typed.hs
{-# LANGUAGE GADTs, ImpredicativeTypes, ConstraintKinds, ScopedTypeVariables #-}
module Build.SelfTracking.Typed (
Fetch, TaskT (..), TasksT, Key (..), selfTracking
) where
import Build.Task
type Fetch k f = forall v. k v -> f v
newtype TaskT c k v = TaskT { runT :: forall f. c f => Fetch k f -> f v }
type TasksT c k = forall v. k v -> Maybe (TaskT c k v)
-- | The type variable @s@ stands for "scripts" written in some task description
-- language.
data Key k v s a where
Script :: k -> Key k v s s -- Keys for build scripts
Value :: k -> Key k v s v -- Keys for all other values
selfTracking :: forall k v s. (s -> Task Monad k v) -> Tasks Monad k s -> TasksT Monad (Key k v s)
selfTracking parse tasks key = case key of
Script k -> getScript <$> tasks k
Value k -> runScript <$> tasks k
where
-- Get the task for building the script
getScript :: Task Monad k s -> TaskT Monad (Key k v s) s
getScript task = TaskT $ \fetch -> task (fetch . Script)
-- Build the script, parse it, and then run the obtained task
runScript :: Task Monad k s -> TaskT Monad (Key k v s) v
runScript task = TaskT $ \fetch -> do
script <- task (fetch . Script)
parse script (fetch . Value)