{-# LANGUAGE TypeFamilies #-}
module Ideas.Common.Strategy.Process
( Process, eqProcessBy, menu, withMenu
, fold, runProcess
) where
import Ideas.Common.Classes
import Ideas.Common.Strategy.Choice
import Ideas.Common.Strategy.Sequence
newtype Process a = P [Menu a (Process a)]
instance Eq a => Eq (Process a) where
(==) = eqProcessBy (==)
instance Functor Process where
fmap f = rec
where
rec (P xs) = P (map g xs)
g = onMenu (\a q -> f a |-> rec q) doneMenu
instance Choice (Process a) where
empty = P [empty]
x .|. y = P [menu x .|. menu y]
x ./. y = P [menu x ./. menu y]
x |> y = P [menu x |> menu y]
instance Sequence (Process a) where
type Sym (Process a) = a
done = P []
a ~> b = P [a |-> b]
P xs .*. P ys = P (xs ++ ys)
sequence ps = P [ x | P xs <- ps, x <- xs ]
instance Fix (Process a)
instance Firsts (Process a) where
type Elem (Process a) = a
firsts = bests . menu
ready = hasDone . menu
runProcess :: Apply f => Process (f a) -> a -> [a]
runProcess p a = withMenu op [a] p
where
op f x = [ c | b <- applyAll f a, c <- runProcess x b ]
menu :: Process a -> Menu a (Process a)
menu (P zs) = rec zs
where
rec [] = doneMenu
rec [x] = x
rec (x:xs) = onMenu (\a (P ys) -> a |-> P (ys ++ xs)) (rec xs) x
withMenu :: Choice b => (a -> Process a -> b) -> b -> Process a -> b
withMenu op e (P zs) = rec zs
where
rec [] = e
rec [x] = onMenu op e x
rec (x:xs) = onMenu (\a (P ys) -> op a (P (ys ++ xs))) (rec xs) x
eqProcessBy :: (a -> a -> Bool) -> Process a -> Process a -> Bool
eqProcessBy eq = rec
where
rec p q = eqMenuBy eq rec (menu p) (menu q)
fold :: Choice b => (a -> b -> b) -> b -> Process a -> b
fold op e = rec
where
rec = withMenu (\a -> op a . rec) e