[Haskell-cafe] Are there standard idioms for lazy, pure error handling?

John Millikin jmillikin at gmail.com
Mon Nov 30 00:22:13 EST 2009

I'm working on a library which needs to operate on large data sets, so
I'd like to use lazy values. The library consists of pure functions
from Text to [Event] and back. Normally, I use Maybe or Either for
error handling in pure code, but using these precludes lazy
evaluation. Using exceptions requires any errors to be handled in IO,
which is annoying.

The "idealized" signatures of the functions are:
import qualified Data.Text.Lazy as TL
data Event = EventA | EventB | EventC
parse :: TL.Text -> Either ParseError [Event]
serialize :: [Event] -> Either SerializeError TL.Text

I've considered two possible error handling modes, both adapted from
procedural language style. The first is simply including errors in the
event list.
import qualified Data.Text as T
parse :: TL.Text -> [Either ParseError Event]
serialize :: [Event] -> [Either SerializeError T.Text] -- use TL.fromChunks

The second uses monadic callbacks, based on side effects:
parse :: Monad m => (Event -> m ()) -> (ParseError -> m ()) -> TL.Text -> m ()
serialize :: Monad m => (T.Text -> m ()) -> (SerializeError -> m ())
-> [Event] -> m ()

The main problem I see with these is that they don't indicate or
enforce that an error terminates the event/text streams. The first
allows multiple errors in a row, or events to follow an error. The
second just "feels" ugly, because using it in pure code requires
clients to build a Writer (possibly wrapped with ErrorT) and deal with
the associated plumbing.

Is there any sort of standard idiom for handling this problem? It
seems that somebody must have run across it before, but the resources
I can find on lazy error handling all assume the code is impure
(returning IO, etc).

More information about the Haskell-Cafe mailing list