> Yes. We decided that having the Get monad as a lazy state monad just > doesn't make sense. It makes this one use case work, but causes more > problems generally. Certainly we need to be able to do lazy binary > deserialisation too, but our feeling is that it should be more explicit > and integrate better with error handling. Using a lazy state monad gives > us neither.
This is valid point. I think I'll just use variant with explicit laziness. > Note also that if we changed runGetState to do any error handling that > this would also break the lazy state monad properties that you were > previously relying upon. I'd appreciate addition of error handling very much. Currently I have to use ErrorT and do checks by hands. I have very simple parsers so it's possible. It's not possible to do such things in general. Trading laziness for error handling is good thing I believe. At the moment it's hard to decode possibly malformed data. On 10/17/09, Duncan Coutts <duncan.cou...@googlemail.com> wrote: > On Sat, 2009-09-19 at 00:36 +0400, Khudyakov Alexey wrote: >> Hello >> >> I run into problems with new binary package. Following function reads a >> list >> of elements one by one until end of stream. List is very long (won't fit >> into >> memory). > > Sorry for the late reply. > >> In binary-0.5.0.1 and earlier it read list lazily. Now it seems that it >> tries >> to read whole list to memory. Program does not produce any output and >> memory >> usage steadily grows. > > Yes. We decided that having the Get monad as a lazy state monad just > doesn't make sense. It makes this one use case work, but causes more > problems generally. Certainly we need to be able to do lazy binary > deserialisation too, but our feeling is that it should be more explicit > and integrate better with error handling. Using a lazy state monad gives > us neither. > >> > getStream :: Get a -> Get [a] >> > getStream getter = do >> > empty <- isEmpty >> > if empty >> > then return [] >> > else do x <- getter >> > xs <- getStream getter >> > return (x:xs) >> >> How could I add laziness to this function to revert to old behavior. > > You can make it explicitly lazy using something like: > > getStream :: Get a -> BS.ByteString -> [a] > getStream getter bs = unfoldr step (bs, 0) > where > step (bs, off) = case runGetState getOne bs off of > (Nothing, _, _ ) -> Nothing > (Just x, bs', off') -> Just (x, (bs', off')) > > getOne = do > empty <- isEmpty > if empty > then return Nothing > else fmap Just getter > > Note the distinct lack of error handling, but if we had runGetState > return an Either then you could still make this code lazy, but you'd > have to decide what to do when you got a decoding error. You could at > this point translate it into a pure error, or enrich your output stream > type to account for the possibility of errors. > > Note also that if we changed runGetState to do any error handling that > this would also break the lazy state monad properties that you were > previously relying upon. > > Duncan > > _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe