# The setup

I'll take a different approach than the other answers.

What if we actually allow statements to be a *new kind* of expression, different from the others? What if that new kind of expression even had its own operations? Let's find out!

Let's say that in our language we actually "embed" the statements into the expressions like this.

A statement can be thought of as an "action." Two actions can be combined to form another action. For example, if you have an action `x` and an action `y`, you can use a sequencing operator (call it `;;`) to combine them into a new action. This new action will first do the `x` action and then do the `y` action.

Say we want to print `1` and then print `2`. These are two actions. You might write this `print(1) ;; print(2)`. Of course, you can come up with much better syntax, this is just for illustration. `;;` is a binary operation that takes two actions and gives you back another action (the "combination" of the two argument actions).

# While loops

Alright, now what is a loop in this language? Well, let's start with a `while` loop. We can actually think of a `while` loop as a *function* that takes a Boolean expression (the conditional) and an action (the body) and returns an action. The action it returns is the action that repeats the while loop body action while the conditional is true.

`while` actually doesn't need to be a keyword here and, in fact, there are ways you could implement it *inside* standard library of the language.

You could write it like this (again using a made-up syntax purely for illustration; there are much better ones):

    while(x > 5,
      (print(x) ;; x := x-1))

It looks like I've just written a while loop in a super weird way. And that is technically true. However, we've also gained something new. Actions are now *first-class values* in our language!

We can actually pass around the loop body I've written above. Say you want to abstract the notion of "looping 15 times." You can write a function

    repeat15 =
      fun(a) =>
        let i := 0
        in
        while(i < 15, (a ;; i := i+1))


Now you could write

    repeat15(print("*"))

and you'll print out 15 `*`s.

Also, if we wanted to, we could distinguish actions from "regular values" (like integers or strings) at a type level. We can do this by creating an `Action<T>` type for actions that produce a value of type `T`. We can distinguish between a string value we already have in our hand from an action that *produces* a string value. And, furthermore, we can pass *both* of those kinds of things around at will.

But what is the difference between an `Action<Int>` and an `Int`? Well, it's the exact same as the difference between `/bin/ls` and a list of files (paraphrasing a quote from Shachaf).

# For loops

A `for` loop (or a `foreach` loop) can be thought of as a function that takes in a list and a "parameterized action" (a function that gives you back an action). It returns an action that does this: it will take each item of the list in turn and give it to the "parametrized action."

For instance,

    for([1,2,3,4], fun(x) => print(x))

would print `1 2 3 4` (writing spaces for newlines).

So, what does a `for` loop return here? It returns an action! It doesn't return any particular value produced by the loop. It returns an action that actually *performs* the loop itself.

I mentioned that we can also have a version of `;;` that passes a result from the first action to the second. Here's what that could look like. Call that operator `-->`:

    getLine() --> (fun(x) => print(length(x)))

This would read in a line from standard input and print its length.

Note that `;;` is just a special case of this:

    a ;; b

is the same as

    a --> (fun(_) => b)

As I've mentioned, you can come up with a better syntax. In fact, there already are better syntaxes. The reason is that these ideas already exist.

And that leads me directly to...

# The punchline

What I've just described is a particular case of the concept of a monad (in the form in which it appears in programming languages).

Now, there is some debate about how people should learn about monads. Ultimately, I can only provide part of the answer for this.

I believe to learn them properly you must experiment with a variety of them. For example, look at the list monad, the reader monad and the proxy monad. There are plenty more, but that is some variety to start with. Think about how the "bind" operation works for each of them works, in each particular case.

In the context of this question, the list monad in particular would be useful to look at. Also, my answer to a question [here](https://stackoverflow.com/questions/23188645/non-monadic-error-handling-in-haskell/23207315#23207315) talks about the `Maybe` and `Either` monads in a somewhat similar style to this answer.

I also did not describe the mathematical laws they must obey (though there is a relatively intuitive way to look at these laws in terms of actions).

I've only scratched the surface of a particular monad here. But hopefully this answer can provide some useful ideas.

The particular monad I've described is roughly like Haskell's `IO` monad, though I've left all calls to `writeIORef`, `readIORef` and `newIORef` implicit. There are many other monads, as well. It remains the case that `-->` is the basic "action combining" operation. In Haskell, this is called `>>=`. There's also an operation that will take a "regular value" and give you an action that simply produces that value without doing anything else. This is sometimes called (in Haskell) `pure` or (confusingly) `return`. It's also sometimes called "unit."