Newer
Older
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
import Control.Applicative
import Control.Monad.Reader
import Control.Monad.Trans.Maybe
import qualified Data.Map.Strict as Map
import Data.Maybe
import GHC.IORef
import Control.Monad.Reduce
import Control.Monad.State.Strict
data RTree l i
= Split (RTree l i) !(RTree l i)
| SplitOn !l (RTree l i) !(RTree l i)
extract :: RTree l i -> i
extract = \case
Split _ rhs -> extract rhs
SplitOn _ _ rhs -> extract rhs
Split lhs rhs ->
Split (lhs >>= f) (rhs >>= f)
SplitOn l lhs rhs ->
SplitOn l (lhs >>= f) (rhs >>= f)
(Split lhs rhs) -> (checkgo lhs <|> go rhs)
(SplitOn _ lhs rhs) -> (checkgo lhs <|> go rhs)
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
checkgo rt = p (extract rt) *> go rt
{-# SPECIALIZE reduce :: (i -> MaybeT IO ()) -> RTree l i -> MaybeT IO i #-}
type Valuation l = Map.Map l Bool
extractL :: (Ord l) => Valuation l -> RTree l i -> i
extractL v = \case
Split _ rhs -> extractL v rhs
SplitOn l lhs rhs -> case Map.lookup l v of
Just False -> extractL v lhs
_ -> extractL v rhs
Done i -> i
reduceL
:: forall m l i
. (Alternative m, Ord l)
=> (Valuation l -> i -> m ())
-> Valuation l
-> RTree l i
-> m i
reduceL p = checkgo
where
checkgo v r = p v (extractL v r) *> go v r
go v = \case
Done i -> pure i
SplitOn l lhs rhs -> case Map.lookup l v 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
Split lhs rhs -> (checkgo v lhs <|> go v rhs)
{-# INLINE reduceL #-}
data ReState l = ReState ![Bool] !(Valuation l)
newtype IRTree l i = IRTree {runIRTree :: ReState l -> (i, ReState l)}
deriving (Functor, Applicative, Monad) via (State (ReState l))
instance (Ord l) => MonadReduce l (IRTree l) where
checkWith = \case
Nothing ->
IRTree \case
ReState (a : as) v -> (a, ReState as v)
ReState [] v -> (False, ReState [] v)
Just l -> IRTree \case
ReState as v@(Map.lookup l -> Just x) -> (not x, ReState as v)
ReState (a : as) v -> (a, ReState as (Map.insert l (not a) v))
ReState [] v -> (False, ReState [] (Map.insert l True v))
reduceI
-> IRTree l i
-> m i
reduceI p v (IRTree m) = go []