
On Mon, 2009-11-30 at 20:10 -0800, John Millikin wrote:
On Mon, Nov 30, 2009 at 03:02, Duncan Coutts
wrote:
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.
Wow, this is perfect! I've extracted that type out into the "failable-list" library[1], with a few added instances for common classes (Monad, Applicative, Traversable, etc).
Nice. The one I've felt is missing in the tar package was a foldl. This is used to fully consume a failable list. It wants to return either the normal foldl result or an error encountered. When consuming with a foldr, the main use case is that you're translating into another lazy data structure which has it's own place to annotate errors. When consuming with a foldl, the main use case is that you're strictly consuming the list and purging out the errors because you want to construct a type that does not have room in it for errors. There seem to be a number of possibilities though: for reference, standard list foldl: foldl :: (b -> a -> b) -> b -> [a] -> b foldl :: (b -> a -> b) -> b -> -> FailableList e a -> Either e b or the final result as Either (e, b) b foldl :: (b -> a -> b) -> b -> (b -> e -> b) -> FailableList e a -> b foldl :: (b -> a -> b) -> b -> (b -> c) -> (b -> e -> c) -> FailableList e a -> b This last one is basically the church encoding of Either (e, b) b. Do we want the partial result at the point the list ended in error? If not then it's a little simpler. Duncan