imprevu-0.1.0: src/Imprevu/Types.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
-- | This module contains the type definitions necessary to build a Nomic rule.
module Imprevu.Types where
import Control.Applicative hiding (Const)
import Control.Lens
import Control.Shortcut
import Control.Monad
import Data.Typeable
import GHC.Generics
-- * Event
-- | Composable events
data EventM n a where
SumEvent :: EventM n a -> EventM n a -> EventM n a -- The first event to fire will be returned
AppEvent :: EventM n (a -> b) -> EventM n a -> EventM n b -- Both events should fire, and then the result is returned
PureEvent :: a -> EventM n a -- Create a fake event. The result is useable with no delay.
EmptyEvent :: EventM n a -- An event that is never fired.
BindEvent :: EventM n a -> (a -> EventM n b) -> EventM n b -- A First event should fire, then a second event is constructed
ShortcutEvents :: [EventM n a] -> ([Maybe a] -> Bool) -> EventM n [Maybe a] -- Return the intermediate results as soon as the function evaluates to True, dismissing the events that hasn't fired yet
SignalEvent :: (Eq s, Typeable s, Show s, Typeable a, Show a) => Signal s a -> EventM n a -- Embed a single Signal as an EventM
LiftEvent :: n a -> EventM n a -- create an event containing the result of the monad evaluation
deriving Typeable
instance Functor (EventM n) where
fmap f a = pure f <*> a
instance Applicative (EventM n) where
pure = PureEvent
(<*>) = AppEvent
instance Alternative (EventM n) where
(<|>) = SumEvent
empty = EmptyEvent
instance Monad (EventM n) where
(>>=) = BindEvent
return = PureEvent
instance MonadPlus (EventM n) where
mplus = SumEvent
mzero = EmptyEvent
instance Shortcutable (EventM n) where
shortcut = ShortcutEvents
type ClientNumber = Int
data Signal s a where
Signal :: s -> Signal s a
deriving instance (Show s, Show a) => Show (Signal s a)
deriving instance (Eq s) => Eq (Signal s a)
deriving instance (Typeable s, Typeable a) => Typeable (Signal s a)
data Input = Input InputField ClientNumber
deriving (Show, Read, Eq, Ord, Typeable, Generic)
-- | Input forms as programmed by the user
data InputField = Text String
| TextArea String
| Button String
| Radio String [(Int, String)]
| Checkbox String [(Int, String)]
deriving (Show, Read, Eq, Ord, Typeable, Generic)
-- data sent back by the form fields
data InputData = RadioData Int
| CheckboxData [Int]
| TextData String
| TextAreaData String
| ButtonData
deriving (Show, Read, Eq, Ord, Typeable)
-- | Type agnostic base signal
data SomeSignal = forall a s. (Typeable a, Typeable s, Show a, Show s) => SomeSignal (Signal s a)
deriving instance Show SomeSignal
-- | Type agnostic result data
data SomeData = forall e. (Typeable e, Show e) => SomeData e
deriving instance Show SomeData
-- * EventInfoN
type EventNumber = Int
type EventName = String
-- EventInfoN holds all infos on an active event
data EventInfoN n = forall a. (Typeable a, Show a) =>
EventInfo {_eventNumber :: EventNumber,
event :: EventM n a,
handler :: (EventNumber, a) -> n (),
_evStatus :: Status,
_env :: [SignalOccurence]}
instance Eq (EventInfoN n) where
(EventInfo {_eventNumber=e1}) == (EventInfo {_eventNumber=e2}) = e1 == e2
instance Ord (EventInfoN n) where
(EventInfo {_eventNumber=e1}) <= (EventInfo {_eventNumber=e2}) = e1 <= e2
instance Show (EventInfoN n) where
show (EventInfo en _ _ s envi) =
"event num: " ++ (show en) ++
", envs: " ++ (show envi) ++
", status: " ++ (show s)
eventNumber :: Lens' (EventInfoN n) EventNumber
eventNumber f (EventInfo e ev h evs env) = fmap (\e' -> (EventInfo e' ev h evs env)) (f e)
evStatus :: Lens' (EventInfoN n) Status
evStatus f (EventInfo e ev h evs env) = fmap (\evs' -> (EventInfo e ev h evs' env)) (f evs)
env :: Lens' (EventInfoN n) [SignalOccurence]
env f (EventInfo e ev h evs env) = fmap (\env' -> (EventInfo e ev h evs env')) (f env)
-- status of an event
data Status = SActive | SDeleted deriving (Eq, Show)
-- data and addres from an occurence of a signal
data SignalOccurence = SignalOccurence {_signalOccData :: SignalData,
_signalOccAddress :: SignalAddress}
deriving instance Show SignalOccurence
-- result data from a signal
data SignalData = forall s a. (Typeable s, Typeable a, Show s, Show a, Eq s) =>
SignalData {signal :: Signal s a,
signalData :: a}
instance Show SignalData where
show (SignalData s sd) = show s ++ " " ++ (show sd)
-- SignalAddress is a representation of the address of a signal in the event tree
type SignalAddress = [SignalAddressElem]
data SignalAddressElem = SumR | SumL | AppR | AppL | BindR | BindL | Shortcut deriving (Show, Read, Ord, Eq, Generic)
makeLenses ''SignalOccurence