build-1.0: src/Build/Multi.hs
-- | Support for multiple-output tasks.
module Build.Multi (Partition, multi) where
import Data.Maybe
import Build.Task
-- | Defines a set partition. For a function to be a valid partition,
-- if @f k == ks@, then:
--
-- * @k \in ks@
--
-- * @forall i \in ks . f i == ks@
type Partition k = k -> [k]
-- | Given a task description with individual multiple-output keys, compute its
-- "closure" supporting all possible combinations of keys.
multi :: Eq k => Partition k -> Tasks Applicative [k] [v] -> Tasks Applicative [k] [v]
multi partition tasks keys
| k:_ <- keys, partition k == keys = tasks keys
| otherwise = Just $ Task $ \fetch ->
sequenceA [ select k <$> fetch (partition k) | k <- keys ]
where
select k = fromMaybe (error msg) . lookup k . zip (partition k)
msg = "Partition invariants violated"