snoyberg / conduit

A streaming data library
895 stars 194 forks source link

[RFC] foldWhile #453

Open ocramz opened 3 years ago

ocramz commented 3 years ago

A specialized version of mapAccumWhile that keeps folding as long as the function argument returns 'Right'

foldWhile :: (Monad m) => (a -> s -> Either s s) -> s -> C.ConduitT a o m s
foldWhile f = loop
  where
    loop !s = C.await >>= maybe (pure s) go
      where
        go a = either (return $!) loop $ f a s
ocramz commented 3 years ago

I found a need for this while writing a family of stochastic gradient descent algorithms; the conduit processes one data point of type a at a time and stops accumulating state when a convergence or divergence criterion is met.

snoyberg commented 3 years ago

Seems reasonable to me. Only complaint I can think of: it hides away information about whether it was an end-of-stream versus a Left value produced by f. It may make more sense to generalize a bit to:

foldWhile :: Monad m => (a -> s -> Either e s) -> s -> ConduitT a o m (Either e s)

Either with fmap (either id id) you recover the original behavior. Thoughts?

ocramz commented 3 years ago

Indeed, your version of foldWhile is clearer. I'll prepare a PR!