diff --git a/rtree.cabal b/rtree.cabal index bfb31809c479de8992263636921707709a204a9c..3e6c2e839d275d720fc2c0b400709570a01b71a2 100644 --- a/rtree.cabal +++ b/rtree.cabal @@ -12,6 +12,7 @@ library exposed-modules: Control.Monad.Reduce Control.RTree + Data.Valuation other-modules: Paths_rtree hs-source-dirs: diff --git a/src/Control/Monad/Reduce.hs b/src/Control/Monad/Reduce.hs index 4bdb12c3426f9b6d298cb5083e6acda1ec5c4c1c..640407a5423c857bcebb897cd54f14bcbb6589e2 100644 --- a/src/Control/Monad/Reduce.hs +++ b/src/Control/Monad/Reduce.hs @@ -40,10 +40,11 @@ module Control.Monad.Reduce ( -- * Helpers onBoth, + liftMaybe, ) where +import Control.Applicative import Control.Monad -import Control.Monad.Trans import Control.Monad.Trans.Maybe import qualified Data.List.NonEmpty as NE import Data.Maybe @@ -145,15 +146,14 @@ collectNonEmpty fn as = do instance (MonadReduce l m) => MonadReduce l (MaybeT m) where splitWith m (MaybeT lhs) (MaybeT rhs) = MaybeT (splitWith m lhs rhs) +-- | Helper that lifts a maybe into MonadPlus (or MaybeT) +liftMaybe :: (MonadPlus m) => Maybe a -> m a +liftMaybe = maybe mzero pure + -- | Returns either of the maybes or combines them if both have values. -onBoth :: (Monad m) => MaybeT m a -> MaybeT m a -> (a -> a -> MaybeT m a) -> MaybeT m a -onBoth mlhs mrhs fn = MaybeT do - runMaybeT mlhs >>= \case - Nothing -> runMaybeT mrhs - Just l -> - runMaybeT mrhs >>= \case - Nothing -> pure (Just l) - Just r -> runMaybeT (fn l r) +onBoth :: (MonadPlus m) => m a -> m a -> (a -> a -> m a) -> m a +onBoth mlhs mrhs fn = + join $ (fn <$> mlhs <*> mrhs) <|> fmap pure mrhs <|> fmap pure mlhs {- | Given a list of ordered options, choose the first that statisfy the constraints, returning the last element if nothing else matches. @@ -164,8 +164,10 @@ linearSearch = foldr1 (<|) . fmap pure {- | Given a list of ordered options, choose the first that statisfy the constraints, potentially returning nothing. -} -linearSearch' :: (MonadReduce l m) => [i] -> MaybeT m i -linearSearch' is = MaybeT $ linearSearch (NE.fromList (fmap Just is ++ [Nothing])) +linearSearch' :: (MonadReduce l m, MonadPlus m) => [i] -> m i +linearSearch' is = do + mp <- linearSearch (NE.fromList (fmap Just is ++ [Nothing])) + liftMaybe mp -- | Given ddmin :: (MonadReduce l m) => [i] -> m [i] diff --git a/src/Control/RTree.hs b/src/Control/RTree.hs index 82cb58a837293b731b3be4b18d0b25d26e06087c..eaf7424160e90b51fb000c10803f7dd6aca90447 100644 --- a/src/Control/RTree.hs +++ b/src/Control/RTree.hs @@ -35,22 +35,22 @@ module Control.RTree ( import Control.Applicative import Control.Monad.Reader +import Control.Monad.State.Strict import Data.Functor.Identity -import qualified Data.Map.Strict as Map import Control.Monad.Reduce -import Control.Monad.State.Strict +import qualified Data.Valuation as Val + +type Valuation = Val.Valuation data RTree l i = SplitWith (Maybe l) (RTree l i) !(RTree l i) | Done i deriving (Functor) -type Valuation l = Map.Map l Bool - extract :: (Ord l) => Valuation l -> RTree l i -> i extract v = \case - SplitWith ml lhs rhs -> case ml >>= (`Map.lookup` v) of + SplitWith ml lhs rhs -> case ml >>= Val.truthValue v of Just False -> extract v lhs _ -> extract v rhs Done i -> i @@ -79,10 +79,10 @@ reduce p = checkgo checkgo v r = p (extract v r) *> go v r go v = \case Done i -> pure i - SplitWith (Just l) lhs rhs -> case Map.lookup l v of + SplitWith (Just l) lhs rhs -> case Val.truthValue v l of Just True -> checkgo v rhs Just False -> checkgo v lhs - Nothing -> checkgo (Map.insert l False v) lhs <|> go (Map.insert l True v) rhs + Nothing -> checkgo (Val.setTruthValue v l False) lhs <|> go (Val.setTruthValue v l True) rhs SplitWith Nothing lhs rhs -> (checkgo v lhs <|> go v rhs) {-# INLINE reduce #-} @@ -104,10 +104,10 @@ instance (Monad m, Ord l) => MonadReduce l (IRTreeT l m) where ReState (uncons -> (a, as)) v -> pure (a, ReState as v) Just l -> \case - ReState as v@(Map.lookup l -> Just x) -> + ReState as v@((`Val.truthValue` l) -> Just x) -> pure (x, ReState as v) ReState (uncons -> (a, as)) v -> - pure (a, ReState as (Map.insert l a v)) + pure (a, ReState as (Val.setTruthValue v l a)) where uncons [] = (True, []) uncons (a : as) = (a, as) diff --git a/src/Data/Valuation.hs b/src/Data/Valuation.hs new file mode 100644 index 0000000000000000000000000000000000000000..443269b4b39b85a62eff55c05f31caf678c22ea3 --- /dev/null +++ b/src/Data/Valuation.hs @@ -0,0 +1,67 @@ +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE LambdaCase #-} + +module Data.Valuation ( + Valuation, + + -- * Constructors + singleton, + fromMap, + fromPairs, + + -- * Destructors + toMap, + toPairs, + + -- * Access + setTruthValue, + truthValue, + condition, + + -- * Helpers + viaMap, + viaMapF, +) where + +import Data.Functor.Identity +import qualified Data.Map.Strict as Map + +newtype Valuation l = Valuation {toMap :: Map.Map l Bool} + +singleton :: (Ord l) => l -> Bool -> Valuation l +singleton l t = fromMap $ Map.singleton l t + +viaMap :: (Map.Map l Bool -> Map.Map l Bool) -> Valuation l -> Valuation l +viaMap fn = runIdentity . viaMapF (Identity . fn) + +viaMapF :: (Functor f) => (Map.Map l Bool -> f (Map.Map l Bool)) -> Valuation l -> f (Valuation l) +viaMapF fn = fmap fromMap . fn . toMap + +fromMap :: Map.Map l Bool -> Valuation l +fromMap = Valuation + +fromPairs :: (Ord l) => [(l, Bool)] -> Valuation l +fromPairs = Valuation . Map.fromList + +toPairs :: Valuation l -> [(l, Bool)] +toPairs = Map.toList . toMap + +truthValue :: (Ord l) => Valuation l -> l -> Maybe Bool +truthValue (Valuation m) = (`Map.lookup` m) + +{- | Conditions a valuation with key value pair, if it conficts with the valuation, +it returns Nothing +-} +condition :: (Ord l) => Valuation l -> l -> Bool -> Maybe (Valuation l) +condition v l t = + viaMapF + ( Map.alterF + \case + Just t' | t' /= t -> Nothing + _ -> Just (Just t) + l + ) + v + +setTruthValue :: (Ord l) => Valuation l -> l -> Bool -> Valuation l +setTruthValue v l t = viaMap (Map.insert l t) v