[Haskell-cafe] Re: [darcs-users] Iteratees, streams, and mmap
Johann Höchtl
johann.hoechtl at gmail.com
Sat Dec 12 16:37:50 EST 2009
On Dec 12, 7:13 pm, Jason Dagit <da... at codersbase.com> wrote:
> Hi Heinrich,
>
> On Sat, Dec 12, 2009 at 2:42 AM, Heinrich Apfelmus <
>
>
>
> apfel... at quantentunnel.de> wrote:
> > Jason Dagit wrote:
> > > My next experiment will be to find ways to express "take this operation
> > and
> > > apply it to a stream without letting the stream leak". One implication is
> > > that gzReadFilePS should not be used outside of a core set of modules
> > which
> > > have been auideted to be resource concious. Another implication is that
> > we
> > > need to be really careful about wether or not we allow returning of
> > > sequences of patches. Possibly, we need several foldl-like functions
> > that
> > > open the stream internally. For example, to process the pending maybe we
> > > should have:
> > > withPending :: (a -> Patch -> a) -> IO a
>
> > > And withPending would start the streaming and make sure that the stream
> > > cannot be visible as a data dependency outside of withPending.
>
> > Just a small comment on a potential flaw in this scheme and the
> > observation that even the rank-2 type trick from the ST s monad
> > wouldn't help.
>
> I would say it does help, but it doesn't make it perfect.
>
>
>
> > Namely, withPending does not guarantee that the stream does not leak,
> > it only makes it more natural/convenient to formulate one's code so that
> > it doesn't leak. In particular, using (:) as argument pretty much
> > defeats the whole purpose:
>
> Right. And the iteratee library points out that your iteratees have to be
> well-behaved (I think there they say "bounded"). I'm well aware of this
> issue and thanks for pointing it out for others who are reading along.
>
>
>
>
>
> > withPending (flip (:))
>
> > Fortunately, the type system can ensure that the patches don't leak.
>
> > withPending :: (forall s. a -> Patch s -> a) -> IO a
>
> > Now, a may not mention s and the type checker will reject flip (:)
> > as argument. See also
>
> > Oleg Kiselyov, Chung-chieh Shan.
> > Lightweight Monadic Regions.
> > http://www.cs.rutgers.edu/~ccshan/capability/region-io.pdf<http://www.cs.rutgers.edu/%7Eccshan/capability/region-io.pdf>
>
> > for an elaboration of this technique.
>
> I'm still on the fence as to whether this style of writing it will add value
> greater than the complexity it brings. I am certainly considering it :)
> The darcs source does other things that are also fairly complex.
>
>
>
>
>
> > However, the line between leaking and not leaking is very thin here. As
> > soon as we are given for example a function
>
> > name :: Patch s -> String
>
> > that discards the s , its results can "leak", in the sense that we
> > could now build a list of names
>
> > foo :: IO [String]
> > foo = withPending . flip $ (:) . name
>
> > Even worse, any type a that doesn't have O(1) space usage will "leak"
>
> > bar :: IO [()]
> > bar = withPending . flip $ const (() :)
>
> > In other words, exporting only a foldl' -like interface does not really
> > prevent us from writing functions that have O(n) instead of O(1) space
> > usage. But trying to rectify that with the forall s trick is a doomed
> > idea, too.
>
> I realize it's not perfect, but the problem we have now is that it's too
> easy to write things that have dismal space usage. If we can't force proper
> space usage, how can we make it more natural to have bounded space? Or at
> least a good approximation.
>
> It seems that:
> * foldl'-style helps
> * rank-n can help
> * no approach I've seen *forces* the behavior we want
> * existing code and bug reports demonstrate we need to improve the
> situation
>
> I'm open to suggestions on how to ensure the code has the space behavior I
> want. Lazy IO* and streams of patches is more compositional and natural to
> Haskell programmers, but it seems that it's too hard to ensure the code has
> reasonable space usage. At least where the darcs source is concerned.
> Therefore, I think the status quo demonstrates that in the darcs source it's
> worth experimenting with alternatives to lazy io and streams. In other
> words, the human effort to make the code behave how we want is currently too
> high and that's the issue I want to address. I don't know how we could make
> it impossible to have space leaks, although that would be interesting.
>
As a beginner to Haskell, I am only 1/3 through RWH, those lines scare
me in a sense to question my effort. I simply can not distinguish if
this discussion is somewhat pathological in a sense that every access
to the outside world imposes dangers and an additional exception
handler here and there and an additional if-statement to handle error
return codes will suffice.
Or lazy evaluation, IO monads and the whole story behind
unsafePerformIO was an additional layer of self-deception and
unpredictable effects from the outside world and lazy evaluation can
NEVER be satisfactory handled.
> (*) Note: Lazy IO itself is used in very few places in darcs these days
> because it has lead to serious bugs. These days me point is more about big
> streams getting retained. Finding where and why has proven difficult.
>
> Thanks,
> Jason
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-C... at haskell.orghttp://www.haskell.org/mailman/listinfo/haskell-cafe
More information about the Haskell-Cafe
mailing list