Conceptually we just "catch" the "exceptional value" and return the value. I use quotes because there's no reason to restrict this value to exceptions. You can return any old value from the loop this way:

Notice how I don't have to define a special variation on the forever function that integrates with ExceptT or break to terminate correctly. Instead, break interacts correctly with forever out-of-the-box thanks to Haskell's laziness: forever only lazily evaluates as many actions as necessary and once the internal ExceptT short-circuits the forever function doesn't demand any further command repetitions.

This library also showcases one of Haskell's nifty features: the GeneralizedNewtypeDeriving language extension. Even though I wrap ExceptT in a Break newtype, I can still configure Break to reuse many of the interfaces that were originally implemented for ExceptT, like this:

Newtypes are probably one of the Haskell features I miss the most when programming in other languages. They are free performance-wise (especially with the recent work on Data.Coerce) and you pay very little code to transport interfaces across newtype boundaries. You get all of the benefits of abstraction and precise types at very little cost.

If you would like to use the break library you can find the library on Hackage or Github.

Then you would provide a specific value by wrapping the value in pure or Just:

>>> greet (pure "John")
"Hello, John"

... or you can use the default by suppling empty or Nothing:

>>> greet empty
"Hello"

The disadvantage to this approach is that Maybe does not implement the IsString, Num, or Fractional type classes, meaning that you cannot use numeric or string literals in place of Maybe. You have to explicitly wrap them in pure or Just.

The optional-args library provides an Optional type that is equivalent to Maybe, but with additional instances for IsString, Num, and Fractional:

The optional-args library also comes with documentation explaining intended usage in detail (almost identical to this post), so if the user clicks on the Optional type they will discover clear instructions on how to use the type.

If you would like to use this, you can find the library on Hackage or Github.