---------------------------------------------------------------------- -- | -- Module : BacktrackM -- Maintainer : PL -- Stability : (stable) -- Portability : (portable) -- -- > CVS $Date: 2005/04/21 16:22:00 $ -- > CVS $Author: bringert $ -- > CVS $Revision: 1.4 $ -- -- Backtracking state monad, with r\/o environment ----------------------------------------------------------------------------- {-# LANGUAGE Rank2Types, MultiParamTypeClasses, FlexibleInstances #-} module GF.Data.BacktrackM ( -- * the backtracking state monad BacktrackM, -- * monad specific utilities member, cut, -- * running the monad foldBM, runBM, foldSolutions, solutions, foldFinalStates, finalStates, -- * reexport the 'MonadState' class module Control.Monad.State.Class, ) where import Data.List import Control.Applicative import Control.Monad import Control.Monad.State.Class ---------------------------------------------------------------------- -- Combining endomorphisms and continuations -- a la Ralf Hinze -- BacktrackM = state monad transformer over the backtracking monad newtype BacktrackM s a = BM (forall b . (a -> s -> b -> b) -> s -> b -> b) -- * running the monad runBM :: BacktrackM s a -> s -> [(s,a)] runBM (BM m) s = m (\x s xs -> (s,x) : xs) s [] foldBM :: (a -> s -> b -> b) -> b -> BacktrackM s a -> s -> b foldBM f b (BM m) s = m f s b foldSolutions :: (a -> b -> b) -> b -> BacktrackM s a -> s -> b foldSolutions f b (BM m) s = m (\x s b -> f x b) s b solutions :: BacktrackM s a -> s -> [a] solutions = foldSolutions (:) [] foldFinalStates :: (s -> b -> b) -> b -> BacktrackM s () -> s -> b foldFinalStates f b (BM m) s = m (\x s b -> f s b) s b finalStates :: BacktrackM s () -> s -> [s] finalStates bm = map fst . runBM bm instance Applicative (BacktrackM s) where pure = return (<*>) = ap instance Monad (BacktrackM s) where return a = BM (\c s b -> c a s b) BM m >>= k = BM (\c s b -> m (\a s b -> unBM (k a) c s b) s b) where unBM (BM m) = m fail _ = mzero instance Functor (BacktrackM s) where fmap f (BM m) = BM (\c s b -> m (\a s b -> c (f a) s b) s b) instance Alternative (BacktrackM s) where empty = mzero (<|>) = mplus instance MonadPlus (BacktrackM s) where mzero = BM (\c s b -> b) (BM f) `mplus` (BM g) = BM (\c s b -> g c s $! f c s b) instance MonadState s (BacktrackM s) where get = BM (\c s b -> c s s b) put s = BM (\c _ b -> c () s b) -- * specific functions on the backtracking monad member :: [a] -> BacktrackM s a member xs = BM (\c s b -> foldl' (\b x -> c x s b) b xs) cut :: BacktrackM s a -> BacktrackM s [(s,a)] cut f = BM (\c s b -> c (runBM f s) s b)