An observation by @jaror made me wonder: why shouldn’t I make my monads “value strict”? I don’t know if I can formally define “value strict” but it means something like “when `m a`

has finished evaluating, `a`

is in WHNF[1]”. (That depends on a definition of “finished evaluating”, and I don’t know that there is one in general.) Anyway, here are some examples demonstrating what I mean.

- For a “value strict” monad,
`return a`

is the same as`return $! a`

- A “value strict”
`State s a`

would be isomorphic to`\s -> ValueStrictPair a s`

, where`data ValueStrictPair a s = MkValueStrictPair !a s`

- A “value strict”
`Either a`

would be`data RightStrictEither e a = Left e | Right !a`

(These observations raise questions regarding whether the state itself in `State`

and the error type in `RightStrictEither`

should also be strict!) “Value strict” monads would have two benefits

- fewer space leaks due to accumulating thunks in values passed around in monadic computations.
- better code generation in general for those monadic computations (see, for example, State monad - memory exhausted - #13 by jaror)

There are two drawbacks

- They violate the monad law
`return a >>= f == f a`

, because`return undefined >>= const (pure ()) == undefined`

. Maybe that’s OK. I don’t know that violating this law only up to strictness is a big deal. - They will do unnecessary work when you really did mean to be lazy. However, I suspect the vast, vast majority of use cases don’t really want to be lazy (like the vast majority of use cases of
`foldl`

really want to be`foldl'`

). It’s simple enough to recover lazy behaviour through`data Lazy a = Lazy a`

(at a very small, although non-zero cost) for those cases.

Have I missed some other drawback? Have I downplayed the importance of one of the two drawbacks above? If I’m defining my own monad, why shouldn’t I make it “value strict”?

[1] weak head normal form