
On Tue, Dec 1, 2009 at 5:29 AM, Heinrich Apfelmus
Duncan Coutts wrote:
On Mon, 2009-11-30 at 06:08 +0000, Malcolm Wallace wrote:
However, if you really want to terminate the stream at the first error, and to reflect this in the type, then I guess you can define your own list type:
data ListThenError e a = Cons a (ListThenError e a) | Error e
Of course this has the disadvantage that then your consumer must change to use this type too.
I've been using this list type quite a lot recently. It's in the 'tar' package for example. It comes with variants of the standard functions foldl, foldr, unfoldr that take into account the error possibility.
At some point we should probably make a package to standardise and document this lazy error handling idiom.
I propose to (trivially) generalize this type to "list with an end"
data ListEnd a b = Cons a (ListEnd a b) | End b
because it may have other uses than just lazy error handling.
This is almost a composition of a non-determism monad transformer with
an exception monad.
Specifically, "LogicT (Either e) a" is (almost) isomorphic with
data NX e a = Cons a (NX e a) | Nil | Error e
reflect :: NX e a -> LogicT (Either e) a
reflect (Cons a r) = return a `mplus` reflect r
reflect Nil = mzero
reflect (Error e) = lift (Left e)
reify :: LogicT (Either e) a -> NX e a
reify m = j $ runLogicT m (\a -> Right . Cons a . j) (Right Nil)
where j = either Error id
--
Dave Menendez