diff options
author | Gregor Kleen <pngwjpgh@users.noreply.github.com> | 2016-07-28 23:14:50 +0200 |
---|---|---|
committer | Gregor Kleen <pngwjpgh@users.noreply.github.com> | 2016-07-28 23:14:50 +0200 |
commit | b2e4264e7849f322cbb2bb592b15d2ea7aec9149 (patch) | |
tree | aea74b3cf9311932e243f7088b0e3377616aa329 | |
parent | 69081d160dbf6f7d06b9cafd876e0fea423b8066 (diff) | |
download | events-b2e4264e7849f322cbb2bb592b15d2ea7aec9149.tar events-b2e4264e7849f322cbb2bb592b15d2ea7aec9149.tar.gz events-b2e4264e7849f322cbb2bb592b15d2ea7aec9149.tar.bz2 events-b2e4264e7849f322cbb2bb592b15d2ea7aec9149.tar.xz events-b2e4264e7849f322cbb2bb592b15d2ea7aec9149.zip |
Switch from monoid to foldable container
-rw-r--r-- | default.nix | 2 | ||||
-rw-r--r-- | events/src/Events/Types.hs | 63 | ||||
-rw-r--r-- | events/src/Events/Types/NDT.hs | 59 | ||||
-rw-r--r-- | events/src/Main.hs | 23 |
4 files changed, 89 insertions, 58 deletions
diff --git a/default.nix b/default.nix index 6cb7da5..f977f6b 100644 --- a/default.nix +++ b/default.nix | |||
@@ -1,5 +1,5 @@ | |||
1 | { pkgs ? (import <nixpkgs> {}) | 1 | { pkgs ? (import <nixpkgs> {}) |
2 | , compilerName ? "ghc7103" | 2 | , compilerName ? "ghc801" |
3 | }: | 3 | }: |
4 | 4 | ||
5 | rec { | 5 | rec { |
diff --git a/events/src/Events/Types.hs b/events/src/Events/Types.hs index 22faf94..0eff7aa 100644 --- a/events/src/Events/Types.hs +++ b/events/src/Events/Types.hs | |||
@@ -1,37 +1,34 @@ | |||
1 | {-# LANGUAGE TemplateHaskell #-} | 1 | {-# LANGUAGE TemplateHaskell #-} |
2 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
3 | {-# LANGUAGE FlexibleInstances #-} | ||
4 | {-# LANGUAGE UndecidableInstances #-} | ||
5 | 2 | ||
6 | module Events.Types | 3 | module Events.Types |
7 | ( TimeRange(..), rangeStart, rangeDuration | 4 | ( TimeRange(..), rangeStart, rangeDuration |
8 | , Event(..), payload, occursWithin | 5 | , Event(..), payload, occursWithin |
9 | , EvalCtx(..), ctxVars, ctxEvents | 6 | , EvalCtx(..), ctxEvents |
10 | , ObjCtx(..), objOccurs, objPayload | 7 | , ObjCtx(..), objVars, objOccurs, objPayload |
11 | , Eval, evaluate | 8 | , Eval, evaluate |
12 | , module Data.Aeson | 9 | , module Data.Aeson |
13 | , module Data.Time.Clock | 10 | , module Data.Time.Clock |
14 | , module Data.Default.Class | 11 | , module Data.Default.Class |
15 | ) where | 12 | ) where |
16 | 13 | ||
17 | import Control.Lens.TH | 14 | import Control.Lens.TH (makeLenses) |
18 | 15 | ||
19 | import Data.Aeson (Object) | 16 | import Data.Aeson (Object) |
20 | 17 | ||
21 | import Data.Time.Clock | 18 | import Data.Time.Clock (UTCTime, NominalDiffTime) |
22 | 19 | ||
23 | import Control.Monad.State.Lazy | 20 | import Control.Monad.State.Lazy (StateT, evalStateT, execStateT) |
24 | import ListT (ListT) | ||
25 | import qualified ListT | ||
26 | 21 | ||
27 | import Data.Default.Class | 22 | import Data.Default.Class (Default(def)) |
28 | 23 | ||
29 | import Data.Monoid | 24 | -- import Data.Monoid |
30 | import Control.Monad.Fix | 25 | import Control.Monad.Fix (MonadFix(mfix)) |
31 | import Control.Lens | 26 | import Control.Lens ((^.), set) |
32 | import Data.Maybe | 27 | import Data.Maybe (catMaybes) |
33 | 28 | ||
34 | import Debug.Trace | 29 | -- import Debug.Trace |
30 | |||
31 | import Events.Types.NDT (NDT, foldNDT) | ||
35 | 32 | ||
36 | data TimeRange = TimeRange | 33 | data TimeRange = TimeRange |
37 | { _rangeStart :: UTCTime | 34 | { _rangeStart :: UTCTime |
@@ -46,40 +43,44 @@ data Event = Event | |||
46 | makeLenses ''Event | 43 | makeLenses ''Event |
47 | 44 | ||
48 | data EvalCtx = EvalCtx | 45 | data EvalCtx = EvalCtx |
49 | { _ctxVars :: Object | 46 | { _ctxEvents :: [Object] |
50 | , _ctxEvents :: [Object] | ||
51 | } deriving (Show) | 47 | } deriving (Show) |
52 | makeLenses ''EvalCtx | 48 | makeLenses ''EvalCtx |
53 | 49 | ||
54 | instance Default EvalCtx where | 50 | instance Default EvalCtx where |
55 | def = EvalCtx | 51 | def = EvalCtx |
56 | { _ctxVars = mempty | 52 | { _ctxEvents = mempty |
57 | , _ctxEvents = mempty | ||
58 | } | 53 | } |
59 | 54 | ||
60 | data ObjCtx = ObjCtx | 55 | data ObjCtx = ObjCtx |
61 | { _objOccurs :: Bool | 56 | { _objOccurs :: Bool |
62 | , _objPayload :: Maybe Object | 57 | , _objPayload :: Maybe Object |
58 | , _objVars :: Object | ||
63 | } | 59 | } |
64 | makeLenses ''ObjCtx | 60 | makeLenses ''ObjCtx |
65 | 61 | ||
66 | instance Default ObjCtx where | 62 | instance Default ObjCtx where |
67 | def = ObjCtx | 63 | def = ObjCtx |
68 | { _objOccurs = False | 64 | { _objOccurs = True |
69 | , _objPayload = Nothing | 65 | , _objPayload = Nothing |
66 | , _objVars = mempty | ||
70 | } | 67 | } |
71 | 68 | ||
72 | objCtx :: ObjCtx -> Maybe Object | 69 | objCtx :: ObjCtx -> Maybe Object |
73 | objCtx (ObjCtx False _) = Nothing | 70 | objCtx ctx |
74 | objCtx (ObjCtx True o) = o | 71 | | ctx ^. objOccurs = ctx ^. objPayload |
72 | | otherwise = Nothing | ||
75 | 73 | ||
76 | type Eval m a = StateT ObjCtx (ListT (StateT EvalCtx m)) a | 74 | -- type Eval m a = StateT ObjCtx (ListT (StateT EvalCtx m)) a |
77 | 75 | ||
78 | evaluate :: MonadFix m => Eval m () -> m [Object] | 76 | -- evaluate :: MonadFix m => Eval m () -> m [Object] {- TODO: Switch to `ListT m Object` – `m [Object]` will turn out to be to strict. There is no instance for `MonadFix (ListT m)` – writing one seems to be possible. -} |
79 | evaluate x = catMaybes <$> mfix x' | 77 | -- evaluate x = catMaybes <$> mfix x' |
80 | where | 78 | -- where |
81 | x' = evalStateT (ListT.toReverseList (objCtx <$> execStateT x def)) . flip (set ctxEvents) def . catMaybes | 79 | -- x' = evalStateT (ListT.toList (objCtx <$> execStateT x def)) . flip (set ctxEvents) def . catMaybes |
82 | 80 | ||
83 | instance MonadState s m => MonadState s (ListT m) where | 81 | type Eval m a = StateT ObjCtx (NDT (StateT EvalCtx m)) a |
84 | get = lift get | 82 | |
85 | put = lift . put | 83 | evaluate :: MonadFix m => (Maybe Object -> StateT EvalCtx m Bool) -> Eval m () -> m [Object] {- TODO: Switch to `ListT m Object` – `m [Object]` will turn out to be to strict. There is no instance for `MonadFix (ListT m)` – writing one seems to be possible. -} |
84 | evaluate predicate x = catMaybes <$> mfix x' | ||
85 | where | ||
86 | x' = evalStateT (foldNDT predicate (objCtx <$> execStateT x def)) . flip (set ctxEvents) def . catMaybes | ||
diff --git a/events/src/Events/Types/NDT.hs b/events/src/Events/Types/NDT.hs index 94a84f0..8431f51 100644 --- a/events/src/Events/Types/NDT.hs +++ b/events/src/Events/Types/NDT.hs | |||
@@ -15,10 +15,13 @@ import Data.Foldable (foldr) | |||
15 | import Data.Maybe | 15 | import Data.Maybe |
16 | import Data.Either | 16 | import Data.Either |
17 | 17 | ||
18 | import Control.Applicative (Alternative) | ||
19 | import qualified Control.Applicative as Alt (Alternative(..)) | ||
18 | import Control.Monad | 20 | import Control.Monad |
19 | import Control.Monad.Identity | 21 | import Control.Monad.Identity |
20 | 22 | ||
21 | import Control.Monad.Trans | 23 | import Control.Monad.Trans |
24 | import Control.Monad.Trans.Maybe | ||
22 | 25 | ||
23 | import Debug.Trace | 26 | import Debug.Trace |
24 | 27 | ||
@@ -43,7 +46,6 @@ instance Applicative m => Applicative (NDT m) where | |||
43 | 46 | ||
44 | instance Applicative m => Monad (NDT m) where | 47 | instance Applicative m => Monad (NDT m) where |
45 | return = pure | 48 | return = pure |
46 | fail = const empty | ||
47 | (>>=) = NDTBind | 49 | (>>=) = NDTBind |
48 | 50 | ||
49 | instance Monad m => Monoid (NDT m a) where | 51 | instance Monad m => Monoid (NDT m a) where |
@@ -56,37 +58,60 @@ instance Monad m => Monoid (NDT m a) where | |||
56 | instance MonadTrans NDT where | 58 | instance MonadTrans NDT where |
57 | lift = NDTCons . fmap Just . fmap (,empty) | 59 | lift = NDTCons . fmap Just . fmap (,empty) |
58 | 60 | ||
61 | instance Monad m => Alternative (NDT m) where | ||
62 | empty = mempty | ||
63 | (<|>) = mappend | ||
64 | |||
65 | instance Monad m => MonadPlus (NDT m) where | ||
66 | mzero = mempty | ||
67 | mplus = mappend | ||
68 | |||
69 | -- instance MonadFix m => MonadFix (NDT m) where | ||
70 | -- mfix f = NDTCons . runMaybeT $ do | ||
71 | -- x <- mfix (head . f) | ||
72 | -- return (x, trace "tail" . mfix $ tail . f) | ||
73 | -- where | ||
74 | -- head :: Monad m => NDT m a -> MaybeT m a | ||
75 | -- head (NDTCons x) = MaybeT . trace "head (cons)" $ fmap fst <$> x | ||
76 | -- head (NDTBind (NDTBind x g) f) = head $ NDTBind x (f <=< g) | ||
77 | -- head (NDTBind (NDTCons x) f) = MaybeT x >>= head . f . fst . trace "head (bind cons)" | ||
78 | -- tail :: Monad m => NDT m a -> NDT m a | ||
79 | -- tail (NDTCons x) = NDTBind (lift x) $ maybe empty snd . guardNothing | ||
80 | -- tail (NDTBind (NDTBind x g) f) = tail $ NDTBind x (f <=< g) | ||
81 | -- tail (NDTBind (NDTCons x) f) = tail . NDTCons $ fmap (\(_, xs) -> (undefined, NDTBind xs f)) <$> x | ||
82 | -- guardNothing :: Maybe a -> Maybe a | ||
83 | -- guardNothing x@(Just _) = x | ||
84 | -- guardNothing x@(Nothing) = trace "Nothing" x | ||
85 | |||
86 | instance MonadIO m => MonadIO (NDT m) where | ||
87 | liftIO = lift . liftIO | ||
88 | |||
59 | empty :: Applicative m => NDT m a | 89 | empty :: Applicative m => NDT m a |
60 | empty = NDTCons $ pure Nothing | 90 | empty = NDTCons $ pure Nothing |
61 | 91 | ||
62 | cons :: Applicative m => a -> NDT m a -> NDT m a | 92 | cons :: Applicative m => a -> NDT m a -> NDT m a |
63 | cons x xs = NDTCons . pure $ Just (x, xs) | 93 | cons x xs = NDTCons . pure $ Just (x, xs) |
64 | 94 | ||
65 | foldNDT :: (Monoid a, Monad m) => (a -> m Bool) -> NDT m a -> m a | 95 | foldNDT :: (Foldable f, Applicative f, Monoid (f a), Monad m) => (a -> m Bool) -> NDT m a -> m (f a) |
66 | foldNDT sel = fmap snd . foldNDT' sel | 96 | -- ^ Evaluate depth-first, pruning leaves under the assumption that the selection predicate is monotonic on siblings and children |
67 | 97 | foldNDT sel (NDTCons mx) = do | |
68 | foldNDT' :: (Monoid a, Monad m) => (a -> m Bool) -> NDT m a -> m (Any, a) | ||
69 | -- ^ Evaluate depth-first, pruning leaves under the assumption that the selection predicate is monotonic on siblings | ||
70 | foldNDT' sel (NDTCons mx) = do | ||
71 | mx' <- mx | 98 | mx' <- mx |
72 | case mx' of | 99 | case mx' of |
73 | Nothing -> return mempty | 100 | Nothing -> return mempty |
74 | Just (x, mxs) -> do | 101 | Just (x, mxs) -> do |
75 | continue <- sel x | 102 | continue <- sel x |
76 | case trace ("(cons "++ show continue ++ ")") continue of | 103 | case trace ("(cons "++ show continue ++ ")") continue of |
77 | False -> return (Any True, mempty) | 104 | False -> return mempty |
78 | True -> ((Any True, x) <>) <$> foldNDT' sel mxs | 105 | True -> (pure x <>) <$> foldNDT sel mxs |
79 | foldNDT' sel (NDTBind (NDTCons x) f) = trace "(bind cons)" $ do | 106 | foldNDT sel (NDTBind (NDTCons x) f) = trace "(bind cons)" $ do |
80 | x' <- x | 107 | x' <- x |
81 | case x' of | 108 | case x' of |
82 | Nothing -> return mempty | 109 | Nothing -> return mempty |
83 | Just (x'', xs) -> do -- foldNDT' sel . NDTCons $ Just . (, NDTBind xs f) . snd <$> foldNDT' sel (f x'') | 110 | Just (x'', xs) -> do |
84 | (productive, x3) <- foldNDT' sel $ f x'' | 111 | x3 <- foldNDT sel $ f x'' |
85 | continue <- sel x3 | 112 | xs' <- if null x3 then return mempty else foldNDT sel (NDTBind xs f) |
86 | case trace ("(bind cons " ++ show (productive, continue) ++ ")") $ continue || not (getAny productive) of | 113 | return $ x3 <> xs' |
87 | False -> return mempty | 114 | foldNDT sel (NDTBind (NDTBind x g) f) = trace "(bind bind)" . foldNDT sel $ NDTBind x (f <=< g) |
88 | True -> ((mempty, x3) <>) <$> foldNDT' sel (NDTBind xs f) | ||
89 | foldNDT' sel (NDTBind (NDTBind x g) f) = trace "(bind bind)" . foldNDT' sel $ NDTBind x (f <=< g) | ||
90 | 115 | ||
91 | fromFoldable :: (Foldable f, Monad m) => f a -> NDT m a | 116 | fromFoldable :: (Foldable f, Monad m) => f a -> NDT m a |
92 | fromFoldable = foldr cons empty | 117 | fromFoldable = foldr cons empty |
diff --git a/events/src/Main.hs b/events/src/Main.hs index 0454f22..a4ffa5a 100644 --- a/events/src/Main.hs +++ b/events/src/Main.hs | |||
@@ -11,18 +11,23 @@ import Control.Lens | |||
11 | import Control.Monad | 11 | import Control.Monad |
12 | import Control.Monad.Trans | 12 | import Control.Monad.Trans |
13 | import Data.Aeson.Lens | 13 | import Data.Aeson.Lens |
14 | import Data.Aeson | ||
15 | 14 | ||
16 | import Debug.Trace | 15 | import Debug.Trace |
17 | 16 | ||
17 | import Data.Maybe (isJust) | ||
18 | |||
18 | import qualified ListT | 19 | import qualified ListT |
20 | import qualified Events.Types.NDT as NDT | ||
19 | 21 | ||
20 | main :: IO () | 22 | main :: IO () |
21 | -- main = test $ [ Nop | 23 | main = test $ do |
22 | -- , Override [("blub", String "Haha!")] | 24 | n <- lift $ NDT.fromFoldable ([1..] :: [Integer]) |
23 | -- , Occurs True | 25 | -- objOccurs .= (n <= 5) |
24 | -- , Occurs False | 26 | objOccurs .= (n >= 2) |
25 | -- ] | 27 | objPayload ?= [ ("num", Yaml.Number $ fromIntegral n) |
26 | -- where | 28 | ] |
27 | -- test = CBS.putStr . Yaml.encode <=< evaluate . interpret | 29 | where |
28 | main = undefined | 30 | test = CBS.putStr . Yaml.encode <=< evaluate predicate |
31 | predicate :: Monad m => Maybe Yaml.Object -> m Bool | ||
32 | predicate Nothing = return True | ||
33 | predicate (Just obj) = return . maybe False (<= 5) . traceShowId $ obj ^. at "num" . asDouble | ||