lazy logging (was: Are there standard idioms for lazy, pure error handling?)

This is only peripherally related, but I also have a lot of list functions that can possibly be an error, but usually processing can continue. So they tend to return [Either Error Result]. I have another function thus: -- A foldr version is not lazy enough and overflows the stack. partition_either [] = ([], []) partition_either (x:xs) = let (ls, rs) = partition_either xs in case x of Left l -> (l:ls, rs) Right r -> (ls, r:rs) I was a little surprised I couldn't find this in the standard library... or maybe it is? Anyway, the trick is logging the errors while incrementally processing the non-errors. Logging them first forces the whole thing. Mixing the logging in with the processing forces the processing to be in IO and is not as nice as having it separate. If the next processing step is also pure, the errors must be propagated. 'map (fmap f)' should do it, as long as the errors are all the same type. It's still not ideal because the logs happen in a bunch at the end, and are still taking up memory meanwhile. The only thing I can think of is the dreaded lazy IO... plain unsafePerformIO wouldn't work because nothing is forcing it. It would be sort of an output version of getContents, but it would have to have some magic to know when a thunk has been evaluated without forcing it. But hey, the debugger does it! And the RTS already happily logs things in the middle of pure computation, so this would just be giving programmers access to it... so it's not *so* crazy :)

Am Dienstag 01 Dezember 2009 20:21:27 schrieb Evan Laforge:
This is only peripherally related, but I also have a lot of list functions that can possibly be an error, but usually processing can continue. So they tend to return [Either Error Result]. I have another function thus:
-- A foldr version is not lazy enough and overflows the stack.
try foldr (\e ~(ls,rs) -> case e of { Left l -> (l:ls,rs); Right r -> (ls,r:rs) }) ([],[]) with the lazy pattern, it should be lazy enough.
partition_either [] = ([], []) partition_either (x:xs) = let (ls, rs) = partition_either xs in case x of Left l -> (l:ls, rs) Right r -> (ls, r:rs)
I was a little surprised I couldn't find this in the standard library... or maybe it is?
Data.Either.partitionEithers Data.List.partition isLeft isLeft (Left _) = True isLeft _ = False

Am Dienstag 01 Dezember 2009 21:00:13 schrieb Daniel Fischer:
Am Dienstag 01 Dezember 2009 20:21:27 schrieb Evan Laforge:
This is only peripherally related, but I also have a lot of list functions that can possibly be an error, but usually processing can continue. So they tend to return [Either Error Result]. I have another function thus:
-- A foldr version is not lazy enough and overflows the stack.
try
foldr (\e ~(ls,rs) -> case e of { Left l -> (l:ls,rs); Right r -> (ls,r:rs) }) ([],[])
with the lazy pattern, it should be lazy enough.
Yup. Tested now.
partition_either [] = ([], []) partition_either (x:xs) = let (ls, rs) = partition_either xs in case x of Left l -> (l:ls, rs) Right r -> (ls, r:rs)
I was a little surprised I couldn't find this in the standard library... or maybe it is?
Data.Either.partitionEithers
And that's not lazy enough, either. Ticket: http://hackage.haskell.org/trac/ghc/ticket/3709
Data.List.partition isLeft
isLeft (Left _) = True isLeft _ = False
Not quite the same.
participants (2)
-
Daniel Fischer
-
Evan Laforge