This package provides the macro `@monadic`

and its little helper `@pure`

.

With both you can define custom monadic syntax, let's look at an example to clarifiy what this means.

```
my_map(f, a::Vector) = f.(a)
my_flatmap(f, a::Vector) = vcat(f.(a)...)
# to show you what flatmap does, a small example
my_flatmap(x -> [x, x], [1, 2]) # [1, 1, 2, 2] i.e. it applies `f` to every element and concatenates all results
using Monadic
@monadic my_map my_flatmap begin
a = [:a,:b]
b = [1, 2]
c = [b + 4, b + 5]
@pure Symbol(a, b, c)
end
# returns [:a15, :a16, :a26, :a27, :b15, :b16, :b26, :b27]
```

Apparently, this use of `@monadic`

works like a nested for-loop, collecting the results.

To summarize what happens is that each line is interpreted as a kind of context or context-assignment (instead of
a usual value or value assignment in normal syntax). With the `@pure`

macro you can indicate that the code should be
interpreted normally (without context).

The context here is defined by our Vector, which we interpreted by `my_map`

and `my_flatmap`

as a kind of "do the computation for all combinations". It is like a context for indeterminism.

So let's read the `@monadic`

syntax out loud:

```
for every a in [:a, :b]
for every b in [1, 2]
for every c in [b + 4, b + 5]
do a normal computation `Symbol(a, b, c)` (because it is prepended with `@pure`)
and collect the last computation for all combinations (because it is the last expression)
```

For more details check out the documentation.

To install the package, use the following command inside the Julia REPL:

```
using Pkg
pkg"add Monadic"
```

To load the package, use the command:

`using Monadic`

It will give you the macros `@monadic`

and `@pure`

.