[Haskell-cafe] Re: Are there standard idioms for lazy,
pure error handling?
Heinrich Apfelmus
apfelmus at quantentunnel.de
Tue Dec 1 05:29:24 EST 2009
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. For
mnemonic value, we could call it a "train":
data Train a b = Wagon a (Train a b)
| Loco b
as it is in analogy with a sequence of wagons of the same type followed
by the locomotive which has a different type.
This data type naturally turns up as the differential of the lists
d [x] = Train x [x]
and the usual zipper ([x],[x]) is actually an optimization:
Train a b == ([a] , b)
Incidentally, this isomorphism corresponds to the alternative approach
you mentioned:
> Another approach that some people have advocated as a general purpose
> solution is to use:
>
> data Exceptional e a = Exceptional {
> exception :: Maybe e
> result :: a
> }
As for other uses of Train , I remember seeing the following fold operation
fold1 :: (a -> b -> b) -> (a -> b) -> [a] -> b
fold1 f g [a] = g a
foldl f g (a:x) = f a (fold1 f g x)
(from
Oege de Moor, Jeremy Gibbons.
"Bridging the Algorithm Gap: A Linear-Time Functional Program
for Paragraph Formatting"
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.47.3229
)
which is of course the natural fold for the Train data type:
fold :: (a -> c -> c) -> (b -> c) -> Train a b -> c
fold f g (Loco b) = g b
fold f g (Wagon a t) = f a (fold f g t)
Regards,
Heinrich Apfelmus
--
http://apfelmus.nfshost.com
More information about the Haskell-Cafe
mailing list