module Quantum.Synthesis.StepComp where
import Control.Applicative (Applicative(..))
import Control.Monad (liftM, ap)
data StepComp a =
Done a
| Tick (StepComp a)
instance Monad StepComp where
return a = Done a
Done a >>= g = g a
Tick f >>= g = Tick (f >>= g)
instance Applicative StepComp where
pure = return
(<*>) = ap
instance Functor StepComp where
fmap = liftM
instance Show a => Show (StepComp a) where
show (Done a) = "Done(" ++ show a ++ ")"
show (Tick c) = "Incomplete"
tick :: StepComp ()
tick = Tick (Done ())
untick :: StepComp a -> StepComp a
untick (Done a) = (Done a)
untick (Tick c) = c
forward :: Int -> StepComp a -> StepComp a
forward 0 c = c
forward n (Done a) = Done a
forward n c = forward (n1) (untick c)
is_done :: StepComp a -> Bool
is_done (Done a) = True
is_done (Tick c) = False
get_result :: StepComp a -> Maybe a
get_result (Done a) = Just a
get_result (Tick c) = Nothing
subtask :: Int -> StepComp a -> StepComp (StepComp a)
subtask n c | n <= 0 = Done c
subtask n (Done a) = Done (Done a)
subtask n (Tick c) = Tick (subtask (n1) c)
speedup :: Int -> StepComp a -> StepComp a
speedup n (Done a) = Done a
speedup n (Tick c) = do
tick
speedup n (forward (n1) c)
parallel :: StepComp a -> StepComp b -> StepComp (Either (a, StepComp b) (StepComp a, b))
parallel (Done a) c = Done (Left (a, c))
parallel c (Done b) = Done (Right (c, b))
parallel (Tick c) (Tick c') = Tick (parallel c c')
with_counter :: StepComp a -> StepComp (a, Int)
with_counter c = aux 0 c where
aux n (Done a) = return (a, n)
aux n (Tick c) = do
n `seq` tick
aux (n+1) c
run :: StepComp a -> a
run (Done a) = a
run (Tick c) = run c
run_with_steps :: StepComp a -> (a, Int)
run_with_steps = run . with_counter
run_bounded :: Int -> StepComp a -> Maybe a
run_bounded n = get_result . forward n
diverge :: StepComp a
diverge = tick >> diverge
parallel_first :: StepComp a -> StepComp a -> StepComp a
parallel_first c1 c2 = do
r <- parallel c1 c2
case r of
Left (a, _) -> return a
Right (_, a) -> return a
parallel_maybe :: StepComp (Maybe a) -> StepComp (Maybe b) -> StepComp (Maybe (a,b))
parallel_maybe c1 c2 = do
res <- parallel c1 c2
case res of
Left (Nothing, c2) -> return Nothing
Right (c1, Nothing) -> return Nothing
Left (Just a, c2) -> do
b <- c2
case b of
Nothing -> return Nothing
Just b -> return (Just (a,b))
Right (c1, Just b) -> do
a <- c1
case a of
Nothing -> return Nothing
Just a -> return (Just (a,b))
parallel_list_maybe :: [StepComp (Maybe a)] -> StepComp (Maybe [a])
parallel_list_maybe [] = return (Just [])
parallel_list_maybe (h:t) = do
res <- parallel_maybe h c2
return $ do
(h',t') <- res
return (h':t')
where
c2 = parallel_list_maybe t