In my previous post, I explained the difference between the lazy and strict state monads. What I didn’t mention in the post is that the state monad is not special in this regard. Other monads also can have both lazy and strict variants. For example, transformers package provides both flavors of monads for `RWS`

and `Writer`

monads too.

It is also possible to have identity monads with either lazy or strict semantics. *transformers* package provides only the lazy variant, but it is not hard to image a strict variant of the identity monad. Here’s the definition of `Control.Monad.StrictIdentity`

defined in strict-identity package.

```
newtype StrictIdentity a = StrictIdentity {runStrictIdentity_ :: a }
instance Monad StrictIdentity where
return !a = StrictIdentity $! a
(!m) >>= (!k) = k $! runStrictIdentity m
```

The strict identity monad when bound to a function always evaluate its argument. We can see that both BangPatterns and the strict application operator `($!)`

are used to enforce strict evaluation of arguments.

In this sense, Eval monad from `Control.Parallel.Strategies`

is also an identity monad. It enforces the strict evaluation of the argument with pattern matching.

```
data Eval a = Done a
instance Monad Eval where
return x = Done x
Done x >>= k = k x -- Note: pattern 'Done x' makes '>>=' strict
```

In Implementing a call-by-value interpreter in Haskell, I mistakenly used the lazy identity monad to force the evaluation order. We need to keep in mind that transforming a program into a monadic form does not automatically guarantees the evaluation order unless the monad is strict.

**UPDATE**: Calling arbitrary monads lazy or strict is not appropriate as each monad has varying degree of strictness. For example, the `StrictIdentity`

is more strict than the `Eval`

monad. See the Reddit discussion thread for details.

```
λ> Control.Monad.StrictIdentity.runStrictIdentity $ do x <- return undefined; return 1
*** Exception: Prelude.undefined
λ> Control.Parallel.Strategies.runEval $ do x <- return undefined; return 1
1
```