module MuCheck.Utils.Syb ( selectMany
, selectOne
, relevantOps
, once
, once') where
import Data.Generics (Data, Typeable, GenericM, gmapMo, everything, mkQ, mkMp)
import MuCheck.MuOp (mkMp', MuOp)
import MuCheck.Utils.Common (safeHead)
import Control.Monad (MonadPlus, mplus)
import Data.Maybe(fromMaybe, isJust)
once :: MonadPlus m => GenericM m -> GenericM m
once f x = f x `mplus` gmapMo (once f) x
once' :: (forall a. Data a => a -> Maybe a) -> (forall a. Data a => a -> a)
once' f x = fromMaybe x $ once f x
selectMany :: (Data a, Typeable b) => (b -> Bool) -> a -> [b]
selectMany f = everything (++) ([] `mkQ` keep f)
where keep fn x = [x | fn x]
selectOne :: (Typeable a, Data a1) => (a -> Bool) -> a1 -> Maybe a
selectOne f p = safeHead $ selectMany f p
relevantOps :: (Data a, Eq a) => a -> [MuOp] -> [MuOp]
relevantOps m mlst = filter (relevantOp m) mlst
where relevantOp m op = isJust $ once (mkMp' op) m