each: Template Haskell library for writing monadic expressions more easily

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.



See README at the bottom.

Getting started: See Each.

[Skip to ReadMe]


Change logNone available
Dependenciesbase (>=4.9 && <5), dlist (>=, template-haskell (>= [details]
Copyright(C) dramforever <dramforever@live.com>
Home pagehttps://github.com/dramforever/each#readme
Source repositoryhead: git clone https://github.com/dramforever/each
UploadedMon Feb 6 15:18:11 UTC 2017 by dramforever




Maintainers' corner

For package maintainers and hackage trustees

Readme for each-

[back to package description]


Inspired by the Scala library of the same name, each is a Template Haskell library that transforms expressions containing invocations of impure subexpressions into do-notation. Just mark your impure subexpressions with bind or ~! and they will be called appropriately, as in this small demo:

ghci> $(each [| "Hello, " ++ (~! getLine) |])
World              <--[keyboard input]
"Hello, World"

With the ApplicativeDo GHC extension, calls to fmap and <*> will be arranged so that you don't need to worry if you use, say, Haxl and needs Applicative for parallelism.

Most constructs where this would make things much more simpler are already supported. In particular, these are okay:

These are some quirks:

If you find something wrong, or really want some feature, feel free to leave an issue.

How it works

The basic structure of an each block is this:

$(each [| ... |])

Inside of this block, three (interchangable) ways are used to mark impure subexpressions:

do-notation is generated according to left-to-right order, and branching is handled.

More demos

A more detailed demo:

ghci> :{
    | $(each [|
    |   "Hey it works"
    |   ++ show (length $
    |     "something"
    |     ++ (~! readFile "/etc/issue")
    |     ++ (~! readFile "/etc/issue.net"))
    | |])
    | :}
"Hey it works64"

Nested binds also work as expected.

ghci> prompt str = putStrLn str *> getLine
ghci> $(each [| "Nah just " ++ (~! prompt ("What's " ++ bind getLine ++ "?")) |])
something          <--[keyboard input]
What's something?
nothing            <--[keyboard input]
"Nah just nothing"