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.

[maintain] [Publish]


See README at the bottom.

Getting started: See Each.

[Skip to Readme]


Change log None available
Dependencies base (>=4.9 && <5), dlist (>=, template-haskell (>= [details]
License BSD-3-Clause
Copyright (C) dramforever <dramforever@live.com>
Author dramforever
Maintainer dramforever@live.com
Category Language
Home page https://github.com/dramforever/each#readme
Source repo head: git clone https://github.com/dramforever/each
Uploaded by dramforever at 2017-02-06T15:18:11Z




Maintainer's Corner

Package maintainers

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"