summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregor Kleen <pngwjpgh@users.noreply.github.com>2016-07-31 00:23:23 +0200
committerGregor Kleen <pngwjpgh@users.noreply.github.com>2016-07-31 00:23:23 +0200
commitd22086666632b707aa210f20ecf10a8cd4e6d4fe (patch)
treedd561d380898dfb0a0e8fc6d98249c965c19c221
parent41d0a0c8c3a66ce48756ad8c2ab0ea87933047c9 (diff)
downloadevents-d22086666632b707aa210f20ecf10a8cd4e6d4fe.tar
events-d22086666632b707aa210f20ecf10a8cd4e6d4fe.tar.gz
events-d22086666632b707aa210f20ecf10a8cd4e6d4fe.tar.bz2
events-d22086666632b707aa210f20ecf10a8cd4e6d4fe.tar.xz
events-d22086666632b707aa210f20ecf10a8cd4e6d4fe.zip
Lambda calculus for computing events at runtime
-rw-r--r--events/src/Events/Eval.hs2
-rw-r--r--events/src/Events/Spec.hs18
-rw-r--r--events/src/Events/Spec/Eval.hs38
-rw-r--r--events/src/Events/Spec/LICENSE29
-rw-r--r--events/src/Events/Spec/Types.hs32
-rw-r--r--events/src/Events/Types.hs20
-rw-r--r--events/src/Main.hs2
7 files changed, 125 insertions, 16 deletions
diff --git a/events/src/Events/Eval.hs b/events/src/Events/Eval.hs
index 280c577..800b38d 100644
--- a/events/src/Events/Eval.hs
+++ b/events/src/Events/Eval.hs
@@ -17,7 +17,7 @@ import Control.Lens
17import Data.Ord (Ordering(..)) 17import Data.Ord (Ordering(..))
18 18
19evaluate :: MonadFix m => (Maybe Object -> ReaderT EvalCtx m Bool) -> Eval m () -> m [Object] 19evaluate :: MonadFix m => (Maybe Object -> ReaderT EvalCtx m Bool) -> Eval m () -> m [Object]
20evaluate predicate x = catMaybes <$> mfix x' 20evaluate predicate (unEval -> x) = catMaybes <$> mfix x'
21 where 21 where
22 x' = runReaderT (foldNDT predicate (preview objCtx <$> execStateT x def)) . flip (set ctxEvents) def . catMaybes 22 x' = runReaderT (foldNDT predicate (preview objCtx <$> execStateT x def)) . flip (set ctxEvents) def . catMaybes
23 23
diff --git a/events/src/Events/Spec.hs b/events/src/Events/Spec.hs
index 2af3446..e098886 100644
--- a/events/src/Events/Spec.hs
+++ b/events/src/Events/Spec.hs
@@ -1,11 +1,13 @@
1{-# LANGUAGE GADTs #-} 1{-# LANGUAGE GADTs, DataKinds, TypeOperators #-}
2 2
3module Events.Spec 3module Events.Spec
4 ( interpret 4 ( interpret
5 , Spec, Cmnd(..), Expr(..) 5 , Spec, Cmnd(..), Expr(..), Elem(..)
6 ) where 6 ) where
7 7
8import Events.Types 8import Events.Types
9import Events.Spec.Types
10import Events.Spec.Eval
9 11
10import Control.Monad ((<=<)) 12import Control.Monad ((<=<))
11import Control.Monad.IO.Class 13import Control.Monad.IO.Class
@@ -17,21 +19,15 @@ import Control.Lens
17 19
18import Debug.Trace 20import Debug.Trace
19 21
20type Spec = [Expr Cmnd] -- most significant last 22type Spec m = Expr (Eval m) '[] Cmnd -- most significant last
21 23
22data Cmnd = COverride Object 24data Cmnd = COverride Object
23 | COccurs Bool 25 | COccurs Bool
24 | CNop 26 | CNop
25 deriving (Show) 27 deriving (Show)
26 28
27data Expr a where 29interpret :: MonadIO m => Spec m -> Eval m ()
28 ELit :: a -> Expr a 30interpret = join . fmap interpretCmnd . evalExpr
29
30interpret :: MonadIO m => Spec -> Eval m ()
31interpret = mapM_ $ interpretCmnd <=< interpretExpr
32
33interpretExpr :: MonadIO m => Expr Cmnd -> m Cmnd
34interpretExpr (ELit a) = return a
35 31
36interpretCmnd :: MonadIO m => Cmnd -> Eval m () 32interpretCmnd :: MonadIO m => Cmnd -> Eval m ()
37interpretCmnd (COverride obj) = objPayload ?= obj 33interpretCmnd (COverride obj) = objPayload ?= obj
diff --git a/events/src/Events/Spec/Eval.hs b/events/src/Events/Spec/Eval.hs
new file mode 100644
index 0000000..3a23e0b
--- /dev/null
+++ b/events/src/Events/Spec/Eval.hs
@@ -0,0 +1,38 @@
1{-# LANGUAGE GADTs, DataKinds, TypeOperators, RankNTypes, ScopedTypeVariables #-}
2
3module Events.Spec.Eval
4 ( evalExpr
5 ) where
6
7import Events.Spec.Types
8
9shift :: forall m ts2 t x. Expr m ts2 x -> Expr m (t ': ts2) x
10shift = shift' LZ
11 where
12 -- shift' :: forall ts1 ts2 t x. Length ts1 -> Expr (ts1 ++ ts2) x -> Expr (ts1 ++ t ': ts2) x
13 shift' :: forall ts1 x. Length ts1 -> Expr m (ts1 ++ ts2) x -> Expr m (ts1 ++ t ': ts2) x
14 shift' _ (ELit x) = ELit x
15 shift' l (EVar v) = EVar $ shiftElem l v
16 shift' l (ELam b) = ELam $ shift' (LS l) b
17 shift' l (EApp f x) = EApp (shift' l f) (shift' l x)
18
19 shiftElem :: forall ts1 u. Length ts1 -> Elem u (ts1 ++ ts2) -> Elem u (ts1 ++ t ': ts2)
20 shiftElem LZ e = ES e
21 shiftElem (LS _) EZ = EZ
22 shiftElem (LS l) (ES e) = ES $ shiftElem l e
23
24
25beta = flip beta' LZ
26beta' :: forall m ts1 ts2 s t. Expr m ts2 s -> Length ts1 -> Expr m (ts1 ++ s ': ts2) t -> Expr m (ts1 ++ ts2) t
27beta' _ _ (ELit x) = ELit x
28beta' e LZ (EVar EZ ) = e
29beta' _ LZ (EVar (ES v)) = EVar v
30beta' _ (LS _) (EVar EZ ) = EVar EZ
31beta' e (LS l) (EVar (ES v)) = shift $ beta' e l (EVar v)
32beta' e l (ELam b) = ELam $ beta' e (LS l) b
33beta' e l (EApp f a) = EApp (beta' e l f) (beta' e l a)
34
35evalExpr :: Expr m '[] t -> Val m t
36evalExpr (ELit a) = a
37evalExpr (ELam a) = a
38evalExpr (EApp f a) = evalExpr $ beta a (evalExpr f)
diff --git a/events/src/Events/Spec/LICENSE b/events/src/Events/Spec/LICENSE
new file mode 100644
index 0000000..c28fee7
--- /dev/null
+++ b/events/src/Events/Spec/LICENSE
@@ -0,0 +1,29 @@
1The code in siblings of this file is either heavily inspired by or copied from [glambda](https://hackage.haskell.org/package/glamba), an interpreter for a simply typed lambda-calculus by Richard Eisenberg under the following license:
2
3Copyright (c) 2015, Richard Eisenberg
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are met:
8
91. Redistributions of source code must retain the above copyright notice, this
10list of conditions and the following disclaimer.
11
122. Redistributions in binary form must reproduce the above copyright notice,
13this list of conditions and the following disclaimer in the documentation
14and/or other materials provided with the distribution.
15
163. Neither the name of the author nor the names of its contributors may be
17used to endorse or promote products derived from this software without
18specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/events/src/Events/Spec/Types.hs b/events/src/Events/Spec/Types.hs
new file mode 100644
index 0000000..665958d
--- /dev/null
+++ b/events/src/Events/Spec/Types.hs
@@ -0,0 +1,32 @@
1{-# LANGUAGE GADTs, DataKinds, PolyKinds, TypeOperators, KindSignatures, TypeFamilies, ExplicitNamespaces #-}
2
3module Events.Spec.Types
4 ( Expr(..)
5 , Val(..)
6 , Elem(..)
7 , Length(..)
8 , type (++)(..)
9 ) where
10
11data Expr :: (* -> *) -> [*] -> * -> * where
12 ELit :: Val m a -> Expr m ctx a
13 EVar :: Elem a ctx -> Expr m ctx a
14 ELam :: Expr m (arg ': ctx) res -> Expr m ctx (arg -> res)
15 EApp :: Expr m ctx (arg -> a) -> Expr m ctx arg -> Expr m ctx a
16
17type family Val m a where
18 Val m (a -> b) = Expr m '[a] b
19 Val m a = m a
20
21data Elem :: a -> [a] -> * where
22 EZ :: Elem x (x ': xs)
23 ES :: Elem x xs -> Elem x (y ': xs)
24
25data Length :: [a] -> * where
26 LZ :: Length '[]
27 LS :: Length xs -> Length (x ': xs)
28
29type family (xs :: [a]) ++ (ys :: [a]) :: [a]
30type instance '[] ++ ys = ys
31type instance (x ': xs) ++ ys = x ': (xs ++ ys)
32infixr 5 ++
diff --git a/events/src/Events/Types.hs b/events/src/Events/Types.hs
index 5320bb3..6a8517b 100644
--- a/events/src/Events/Types.hs
+++ b/events/src/Events/Types.hs
@@ -1,11 +1,11 @@
1{-# LANGUAGE TemplateHaskell #-} 1{-# LANGUAGE TemplateHaskell, GeneralizedNewtypeDeriving #-}
2 2
3module Events.Types 3module Events.Types
4 ( TimeRange(..), rangeStart, rangeDuration 4 ( TimeRange(..), rangeStart, rangeDuration
5 , Event(..), payload, occursWithin 5 , Event(..), payload, occursWithin
6 , EvalCtx(..), ctxEvents 6 , EvalCtx(..), ctxEvents
7 , ObjCtx(..), objVars, objOccurs, objPayload, objCtx 7 , ObjCtx(..), objVars, objOccurs, objPayload, objCtx
8 , Eval 8 , Eval(..)
9 , module Data.Aeson 9 , module Data.Aeson
10 , module Data.Time.Clock 10 , module Data.Time.Clock
11 , module Data.Default.Class 11 , module Data.Default.Class
@@ -28,6 +28,8 @@ import Events.Types.NDT (NDT, foldNDT)
28import Control.Monad.State.Lazy 28import Control.Monad.State.Lazy
29import Control.Monad.Reader 29import Control.Monad.Reader
30 30
31import Control.Applicative (Alternative(..))
32
31data TimeRange = TimeRange 33data TimeRange = TimeRange
32 { _rangeStart :: UTCTime 34 { _rangeStart :: UTCTime
33 , _rangeDuration :: NominalDiffTime 35 , _rangeDuration :: NominalDiffTime
@@ -69,4 +71,16 @@ objCtx fObj ctx
69 | ctx ^. objOccurs = traverseOf (objPayload . _Just) fObj ctx 71 | ctx ^. objOccurs = traverseOf (objPayload . _Just) fObj ctx
70 | otherwise = pure ctx 72 | otherwise = pure ctx
71 73
72type Eval m a = StateT ObjCtx (NDT (ReaderT EvalCtx m)) a 74newtype Eval m a = Eval { unEval :: StateT ObjCtx (NDT (ReaderT EvalCtx m)) a }
75 deriving ( MonadState ObjCtx
76 , MonadReader EvalCtx
77 , MonadIO
78 , Functor
79 , Applicative
80 , Alternative
81 , Monad
82 , MonadPlus
83 )
84
85instance MonadTrans Eval where
86 lift = Eval . lift . lift . lift
diff --git a/events/src/Main.hs b/events/src/Main.hs
index e4b255f..410ea1d 100644
--- a/events/src/Main.hs
+++ b/events/src/Main.hs
@@ -22,7 +22,7 @@ import qualified Events.Types.NDT as NDT
22 22
23main :: IO () 23main :: IO ()
24main = test $ do 24main = test $ do
25 n <- lift $ NDT.fromFoldable ([1..] :: [Integer]) 25 n <- Eval . lift $ NDT.fromFoldable ([1..] :: [Integer])
26 lower <- filter (maybe False (< fromIntegral n) <$> view (at "num" . asDouble)) <$> view ctxEvents 26 lower <- filter (maybe False (< fromIntegral n) <$> view (at "num" . asDouble)) <$> view ctxEvents
27 -- objOccurs .= (n <= 5) 27 -- objOccurs .= (n <= 5)
28 objOccurs .= (n >= 2) 28 objOccurs .= (n >= 2)