{-# LANGUAGE DeriveFunctor, RankNTypes #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} -- | The \"free\" structures for dependencies, providing either an applicative -- interface (for 'Depend') or a monadic interface (for 'Depends'). By passing -- them to a suitable 'Task' you can reconstruct all necessary dependencies. module Build.Task.Depend (toDepend, Depend (..), toDepends, Depends (..)) where import Build.Task ----------------------------- Free Task Applicative ---------------------------- -- | A list of dependencies, and a function that when applied to those -- dependencies produces the result. data Depend k v r = Depend [k] ([v] -> r) deriving Functor instance Applicative (Depend k v) where pure v = Depend [] (\[] -> v) Depend d1 f1 <*> Depend d2 f2 = Depend (d1++d2) $ \vs -> let (v1,v2) = splitAt (length d1) vs in f1 v1 $ f2 v2 toDepend :: Task Applicative k v -> Depend k v v toDepend f = f $ \k -> Depend [k] $ \[v] -> v -------------------------------- Free Task Monad ------------------------------- -- | A list of dependencies, and a function that when applied to those -- dependencies either the result or more dependencies. data Depends k v r = Depends [k] ([v] -> Depends k v r) | Done r deriving Functor instance Applicative (Depends k v) where pure = return f1 <*> f2 = f2 >>= \v -> ($ v) <$> f1 instance Monad (Depends k v) where return = Done Done x >>= f = f x Depends ds op >>= f = Depends ds $ \vs -> f =<< op vs toDepends :: Task Monad k v -> Depends k v v toDepends f = f $ \k -> Depends [k] $ \[v] -> Done v