Laughter

Laughter

Laughter is a monad intended for SMILEd job files.

Goals

Definition

data Laughter a where
  Yield :: a -> Laughter a
  Bash :: T.Text -> Laughter ExitCode
  Feed :: Laughter b -> (b -> Laughter a) -> Laughter a
  IO :: IO a -> Laughter a
  Req :: Read a => SmileRequest -> Laughter a
  Err :: T.Text -> Laughter a
  Set :: Typeable s => s -> Laughter ()
  Get :: Typeable s => Laughter s
  Try :: Laughter a -> Laughter (Either T.Text a)
  Foreground :: Laughter a -> Laughter a
  Detach :: Laughter a -> Laughter (ForkId a)
  Wait :: ForkId a -> Laughter a

Doing IO

Laughter is an instance of MonadIO, so you can just use liftIO to embed IO code. The instance is defined like the following:

instance MonadIO Laughter where
  liftIO = IO

For some standard IO functions System.Smile.Jobfile provides replacements, for example:

putStr :: Text -> Laughter ()
putStrLn :: Text -> Laughter ()

More are coming soon. However, putStr and putStrLn should not be used - instead please use the following functions:

emergency :: Text -> Laughter ()
alert :: Text -> Laughter ()
critical :: Text -> Laughter ()
error :: Text -> Laughter ()
warning :: Text -> Laughter ()
notice :: Text -> Laughter ()
info :: Text -> Laughter ()
debug :: Text -> Laughter ()
emit :: LogTag -> T.Text -> Laughter ()

There is also a function called “die”, which prints an error message using the given function, sets the job’s state to Failed and exits immediately.

die :: (T.Text -> Laughter ()) -> T.Text -> Laughter ()
-- e.g.  die emergency "The killer ducks have escaped!"

Global state

If your job needs to save some global variable that can be accessed at all job states (starting, stopping, ...), please declare a new type for it and use the functions get, gets and set:

-- signatures
set :: Typeable s => s -> Laughter ()
get :: Typeable s => Laughter s
gets :: Typeable s => (s -> a) -> Laughter a

-- example
data MyRecState = MyRecState { duckCount :: Int, duckVariety :: Text } deriving (Typeable)
newtype MyStackHeight = MyStackHeight Int deriving (Typeable)

start :: Laughter ()
start = do
  -- ...
  set $ MyRecState 50 "Common Domestic Duck"
  set $ MyStackHeight 12
  -- ...
  count <- gets duckCount
  MyRecState count variety <- get
  MyStackHeight height <- get
  -- ...

As you see, no variable ID, pointer, reference or similar is passed. This is comfortable, but it also means that there can always be only one variable per type. If you want to store more variables of the same data type, use a newtype wrapper (or a list...)

One type is special though: JobState. Setting a value of the type JobState will not only set a script-global variable, but also affect how the job is seen by smiled.

set Starting -- signal smiled that we're still starting
set Running -- signal smiled that we started successfully and the process is now running
set Done -- signal smiled that we fulfilled all our duties and the process exited with success
set Failed -- signal smiled that an error occured; however this does not throw an exception (use 'throwError' or 'die' for that)
Older versions Editor Timestamp
Laughter m@doomanddarkness.eu 2016-10-25 22:24:36 UTC
Laughter m@doomanddarkness.eu 2016-10-25 22:18:10 UTC
Laughter m@doomanddarkness.eu 2016-10-22 10:37:05 UTC
Laughter m@doomanddarkness.eu 2016-10-21 22:46:50 UTC