lambdabot-4.1: scripts/Djinn/MonadBFS.hs
module MonadBFS(MonadBFS(..), BFS, runBFS) where
import Control.Monad
class MonadPlus m => MonadBFS m where
mwrap :: m a -> m a
data Tree a = Tip a | Fork (BFS a)
deriving (Show)
newtype BFS a = BFS { unBFS :: [Tree a] }
deriving (Show)
instance Functor BFS where
fmap f (BFS xs) = BFS $ map tmap xs
where tmap (Tip a) = Tip (f a)
tmap (Fork x) = Fork (fmap f x)
instance Monad BFS where
return a = BFS [Tip a]
fs >>= f = fjoin $ fmap f fs
fjoin :: BFS (BFS a) -> BFS a
fjoin = BFS . concatMap tjoin . unBFS
where tjoin (Tip x) = unBFS x
tjoin (Fork x) = [Fork $ fjoin x]
instance MonadPlus BFS where
mzero = BFS []
BFS f1 `mplus` BFS f2 = BFS $ f1 ++ f2
instance MonadBFS BFS where
mwrap x = BFS [Fork x]
type Q a = ([a],[a])
mtq :: Q a
mtq = ([], [])
enq :: [a] -> Q a -> Q a
enq as ([], []) = (reverse as, [])
enq as (f, r) = (f, as ++ r)
deq :: Q a -> Maybe (a, Q a)
deq ([], []) = Nothing
deq ([a], r) = Just (a, (reverse r, []))
deq (a:f, r) = Just (a, (f, r))
deq _ = error "deq"
runBFS :: BFS a -> [a]
runBFS fr = run (enq [fr] mtq)
where run aq =
case deq aq of
Nothing -> []
Just (BFS xs, q) ->
[x | Tip x <- xs] ++
run (enq [ f | Fork f <- xs] q)