[Haskell-cafe] Takusen and strictness

Stefan O'Rear stefanor at cox.net
Fri Mar 2 10:13:16 EST 2007


On Fri, Mar 02, 2007 at 02:58:21PM +0000, Paul Moore wrote:
> On 02/03/07, Bayley, Alistair <Alistair_Bayley at invescoperpetual.co.uk> 
> wrote:
> >There's a big difference between getContents and Takusen: getContents
> >has a non-trivial implementation (using unsafeInterleaveIO) that allows
> >it to return data lazily. Takusen has no such implementation.
> 
> ... ie, there's deep dark magic involved in the seemingly simple
> getContents, which isn't easily available to mere mortals (or even
> semi-immortal library designers). That figures. It's a shame, but not
> totally unsurprising.

I think I understand it ... here a some illustrative (I hope!) examples:

stefan at stefans:~$ ghci
   ___         ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |      GHC Interactive, version 6.7.20070223, for Haskell 98.
/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|      Type :? for help.

Loading package base ... linking ... done.
Prelude> :m + System.IO.
System.IO.Error   System.IO.Unsafe
Prelude> :m + System.IO.Unsafe
Prelude System.IO.Unsafe> foo <- unsafeInterleaveIO (putStr "foo")  -- note that IO does NOT happen immediately
Prelude System.IO.Unsafe> show foo  -- but forcing it causes the IO to happen (unsafely interleaved with printing (pun intentional))
"foo()"
Prelude System.IO.Unsafe> show foo  -- but now that it is in WHNF, forcing it again has no effect (laziness)
"()"
Prelude System.IO.Unsafe> -- a more interesting case is using unsafeInterleaveIO in list recursion
Prelude System.IO.Unsafe> let myGetContents = unsafeInterleaveIO $ do { ch <- getChar; chs <- myGetContents ; return (ch:chs) }
Prelude System.IO.Unsafe> -- simplified by omitting support for EOF handling and block reads
Prelude System.IO.Unsafe> print . map reverse . lines =<< myGetContents
f["oo?
?oof"Interrupted.
Prelude System.IO.Unsafe> mapM_ putStrLn . map reverse . lines =<< myGetContents
foo?
?oof
bar!
!rab
muahahaha.
.ahahahaum
^D^?

Interrupted.
Prelude System.IO.Unsafe>


> 
> >> That's what my earlier code looked like, and I found it harder to
> >> understand than the getContents/process/put approach. I'm trying to
> >> explore ways of factoring data manipulation code out of database
> >> access functions, but maybe that's not the right way of doing it.
> >
> >I don't think it's possible to pursue this style of programming with
> >Takusen. If you do, you'll have to process the entire result-set into a
> >data structure and then process it, which has obvious memory
> >implications.
> 
> Oh, well. It's mostly irrelevant for me anyway, as the data sets I'm
> actually playing with are small enough that slurping them into memory
> isn't an issue - so I just choose between a simple and decoupled
> implementation or a more complex and scalable one, which is a fairly
> standard optimisation choice.
> 
> Thanks for clarifying.
> Paul.
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe

HTH

Stefan


More information about the Haskell-Cafe mailing list