packages feed

laborantin-hs 0.1.4.0 → 0.1.5.0

raw patch · 3 files changed

+168/−16 lines, 3 filesdep +asyncdep ~base

Dependencies added: async

Dependency ranges changed: base

Files

Laborantin/CLI.hs view
@@ -7,6 +7,8 @@ import Control.Monad import Control.Applicative import Control.Monad.IO.Class+import Control.Concurrent+import Control.Concurrent.Async import Laborantin import Laborantin.Types import Laborantin.Implementation@@ -67,6 +69,7 @@ data Labor = Run        { scenarii   :: [String]                         , params :: [String]                         , matcher :: [String]+                        , concurrency :: Int                         }            | Continue   { scenarii   :: [String]                         , params :: [String]@@ -129,6 +132,12 @@                                     , Help "Restrict to a matching expression"                                     , ArgHelp "MATCHER EXPRESSION"                                     ]+                    ,   concurrency  %> [ Short "c"+                                    , Long ["concurrency"]+                                    , Help "Number of experiments to run at a same time"+                                    , ArgHelp "CONCURRENT RUNS"+                                    , Default (1::Int)+                                    ]                     ]  instance RecordCommand Labor where@@ -182,7 +191,16 @@ filterDescriptions (ScenarioName []) xs = xs filterDescriptions (ScenarioName ns) xs = filter ((flip elem ns) . sName) xs +concurrentmapM_ :: Int -> (a -> IO b) -> [a] -> IO ()+concurrentmapM_ n f xs = do+    goChan <- newChan :: IO (Chan ())+    joinChan <- newChan :: IO (Chan ())+    let f' a = readChan goChan >> f a >> writeChan goChan () >> writeChan joinChan ()+    mapM_ (async . f') xs+    replicateM_ n (writeChan goChan ()) +    mapM_ (\_ -> readChan joinChan) xs + runLabor :: [ScenarioDescription EnvIO] -> Labor -> IO () runLabor xs labor = do     now <- getCurrentTime@@ -191,7 +209,7 @@         Find {}                         -> do execs <- runEnvIO (loadMatching now)                                               mapM_ (T.putStrLn . describeExecution) execs         Rm {}                           -> runSc (loadAndRemove now)-        Run {}                          -> mapM_ runSc (targetExecs [])+        Run {}                          -> do concurrentmapM_ (concurrency labor) runSc (targetExecs [])         Continue {}                     -> do execs <- runEnvIO (loadMatching now)                                               mapM_ runSc (targetExecs execs)         Analyze {}                      -> runSc (loadAndAnalyze now)
README.md view
@@ -1,11 +1,145 @@ laborantin-hs ============= -Initially, Laborantin is a Ruby framework for controlling and managing-experiments. Laborantin-Hs is the Haskell port of Laborantin.+Laborantin is a Haskell framework for running controlled experiments.+It is already quite stable and only few things should change in the near+future. Comments and pull requests are warmly welcome. -# Introduction+# Install +The easiest way to install Laborantin is to use the package published on+hackage.++```sh+  cabal update+  cabal install laborantin-hs+```++Alternatively you can clone this repository with git to get the latest+development version.++```sh+  git clone https://github.com/lucasdicioccio/laborantin-hs	+  cd laborantin-hs+  cabal update+  cabal sandbox init # only if you want a sandboxed install+  cabal install # you can also use cabal configure && cabal build to just build the repo+```++# Two-minutes tutorial++When using Laborantin the typical workflow is as follows:++1. Write one or multiple scenarios using the DSL, e.g. ```my-experiment.hs```.+2. Compile the application with ```ghc --make -O2 my-experiment.hs```. If you built Laboratin using a sandbox, you need to specify the local package database, e.g.++        ghc -no-user-package-db \+            -package-db /path/to/laboratin/.cabal-sandbox/x86_64-linux-ghc-7.6.3-packages.conf.d \+            --make -O2 my-experiment.hs++3. Run experiments with++        ./my-experiment run -m "@sc.param 'some-param' in [42, 'toto'] and @sc.param 'other-param' == 1234"+++Example, annotated, code is as follows. Inline comments start with "--". Please+note that the actual implementation of the `executePingCommand` is left as an+exercise.++```haskell+{-# LANGUAGE OverloadedStrings #-}++module Main where+-- import the world+import Data.Text (Text)+import Control.Monad.IO.Class (liftIO)+import Laborantin.DSL+import Laborantin.Types+import Laborantin.CLI+import Laborantin.Implementation++-- declare one scenario+ping :: ScenarioDescription EnvIO+ping = scenario "ping" $ do -- start defining a scenario called "ping"+  -- enters the description for this scenario+  describe "ping to a remote server"+  -- declares a first parameter, called "destination".+  -- this parameter has some description for documentation purposes+  -- we should explore two values (strings) by default for this parameter+  parameter "destination" $ do+    describe "a destination server (host or ip)"+    values [str "example.com", str "probecraft.net"]+  -- declares a second parameter, called "packet-size".+  -- we should also explore two values (rational numbers) by default for this+  -- parameter+  parameter "packet-size" $ do+    describe "packet size in bytes"+    values [num 50, num 1500] ++  -- now implement the "run hook", which is the actual code to run+  run $ do+    (StringParam srv) <- param "destination" -- lookup "destination" parameter, it should be a string+    (NumberParam ps) <- param "packet-size" -- lookup "packet-size" parameter, it should be a rational number+    liftIO (executePingCommand srv ps) >>= writeResult "raw-result" -- executes the ping action defined below, and dumps the result into a file called "raw-result"+    where executePingCommand :: Text -> Rational -> IO (Text)+          executePingCommand host packetSize = ...++-- list your scenarios in the defaultMain to get a command-line app+main :: IO ()+main = defaultMain [ping]+```++At first, it looks like Laborantin requires a lot of boilerplate if your+experiment is a one-liner. Nothing is free and this is the small cost you have+to pay.  However you get a handy command-line tool for this cost.++For instance, you get some documentation command: `./my-experiment describe` will output:++```+# Scenario: ping+    ping to a remote server+    4 parameter combinations by default+## Parameters:+### destination+(destination)+    a destination server (host or ip)+    2 values:+    - StringParam "example.com"+    - StringParam "probecraft.net"++### packet-size+(packet-size)+    packet size in bytes+    2 values:+    - NumberParam (50 % 1)+    - NumberParam (1500 % 1)+```++You can run experiments with: `./my-experiment run` (stripped output).++```+backend> execution finished++backend> "preparing ping"+backend> "resolving dependencies"+backend> scenario: "ping"+         rundir: results/ping/81e44c78-4fd8-4ab9-8f97-5494dac646a2+         json-params: {"packet-size":{"val":1500.0,"type":"num"},"destination":{"val":"probecraft.net","type":"string"}}++backend> execution finished+```++Then find where experiments results are located with: `./my-experiment find`.++```+results/ping/2ead949a-ed36-4523-9a9c-7c7e2c22a1b2 ping (Success) {"packet-size":{"val":1500.0,"type":"num"},"destination":{"val":"example.com","type":"string"}}+results/ping/81e44c78-4fd8-4ab9-8f97-5494dac646a2 ping (Success) {"packet-size":{"val":1500.0,"type":"num"},"destination":{"val":"probecraft.net","type":"string"}}+results/ping/866b63e8-d407-442c-bc33-f1fb4e96c2a8 ping (Success) {"packet-size":{"val":50.0,"type":"num"},"destination":{"val":"example.com","type":"string"}}+results/ping/a34826bc-5160-4e12-95cc-12fb5c02fc7b ping (Success) {"packet-size":{"val":50.0,"type":"num"},"destination":{"val":"probecraft.net","type":"string"}}+```++# Discussion+ Designing scientific experiments is hard. Scientific experiments often must test an hypothesis such as *does parameter X* influences the outcome of *process A* ? Experimenters must write code to run the *process A*, a task that may be daunting@@ -112,10 +246,10 @@  # Roadmap -For version 0.1.5.x+For version 0.1.6.x -* [improvement] Use system locale rather than default locale for time parsing-    - actually might not be such a good idea, let everyone input %d/%d/%y+* [improvements] changes 'require' to support parametrization+  - needs to pass extra arguments * [feature] exports to propose exported files using "show-exports" command * [feature] labor-script binary for easy-integration of other scripts   - will need to expand parameter spaces by extending undeclared parameters
laborantin-hs.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                laborantin-hs-version:             0.1.4.0+version:             0.1.5.0 synopsis:            an experiment management framework description:              Laborantin is a framework and DSL to run and manage results from scientific@@ -11,15 +11,15 @@     .     Writing experiments with Laborantin has at least two advantages over     rolling your own scripts.  First, Laborantin standardizes the workflow of your-    experimentations.  There is one-way to describe what a project can do, what-    experiments where already run, how to delete files corresponding to a specific-    experiment etc.  Second, Laborantin builds on years of experience running-    experiments. Using Laborantin    should alleviates common pain points such as-    querying for experiments, managing dependencies between results+    experimentations.  There is one way to describe what a project can do, what+    experiments were already run, how to delete files corresponding to a specific+    experiment, etc.  Second, Laborantin builds on years of experience running+    experiments. Using Laborantin    should alleviate common pain points such as+    querying for experiments, managing dependencies between results, etc.     .     Laborantin's DSL lets you express experiment parameters,     setup, teardown, and recovery hooks in a systematic way.-    In addition, this DSL let you express dependencies on your+    In addition, the DSL lets you express dependencies on your     experiments so that you can run prior experiments or data analyses.     .     Laborantin comes with a default backend that stores@@ -62,7 +62,7 @@   exposed-modules:     Laborantin, Laborantin.DSL, Laborantin.Implementation, Laborantin.Types, Laborantin.CLI, Laborantin.Query   other-modules:       Laborantin.Query.Parse, Laborantin.Query.Interpret   other-extensions:    FlexibleContexts, OverloadedStrings, TupleSections-  build-depends:       base >=4.6 && <4.7, transformers >=0.3 && <0.4, mtl >=2.1 && <2.2, containers >=0.5 && <0.6, text >=0.11 && <0.12, bytestring >=0.10 && <0.11, aeson >=0.6 && <0.7, uuid >=1.2 && <1.3, directory >=1.2 && <1.3, random >=1.0 && <1.1, hslogger >=1.2 && <1.3, cmdlib >= 0.3.5, split >= 0.2.2, time >= 1.4.0.1, parsec >= 3.1.0, old-locale >=1.0.0.5+  build-depends:       base >=4.6 && <4.8, transformers >=0.3 && <0.4, mtl >=2.1 && <2.2, containers >=0.5 && <0.6, text >=0.11 && <0.12, bytestring >=0.10 && <0.11, aeson >=0.6 && <0.7, uuid >=1.2 && <1.3, directory >=1.2 && <1.3, random >=1.0 && <1.1, hslogger >=1.2 && <1.3, cmdlib >= 0.3.5, split >= 0.2.2, time >= 1.4.0.1, parsec >= 3.1.0, old-locale >=1.0.0.5, async >= 2.0.1.0   -- hs-source-dirs:         default-language:    Haskell2010 @@ -70,5 +70,5 @@   main-is: main.hs   ghc-options: -Wall   hs-source-dirs: examples-  build-depends:       base >=4.6 && <4.7, transformers >=0.3 && <0.4, mtl >=2.1 && <2.2, containers >=0.5 && <0.6, text >=0.11 && <0.12, bytestring >=0.10 && <0.11, aeson >=0.6 && <0.7, uuid >=1.2 && <1.3, directory >=1.2 && <1.3, random >=1.0 && <1.1, hslogger >=1.2 && <1.3, cmdlib >= 0.3.5, split >= 0.2.2, laborantin-hs >= 0.1.1.2+  build-depends:       base >=4.6 && <4.8, transformers >=0.3 && <0.4, mtl >=2.1 && <2.2, containers >=0.5 && <0.6, text >=0.11 && <0.12, bytestring >=0.10 && <0.11, aeson >=0.6 && <0.7, uuid >=1.2 && <1.3, directory >=1.2 && <1.3, random >=1.0 && <1.1, hslogger >=1.2 && <1.3, cmdlib >= 0.3.5, split >= 0.2.2, laborantin-hs >= 0.1.1.2   default-language:    Haskell2010