[Haskell] lazy constructors

Serge D. Mechveliani mechvel at botik.ru
Wed Oct 13 01:59:37 EDT 2004

Dear Haskellers,

I try to organize a `lazy' output in my program, so that the 
data are accumulated, step by step in a pair
                                             (String, String)
(a contrived simplified example).
And the first component is a `story' to be printed out in a `lazy'
manner, the first steps need to print without waiting for the whole
data field to be ready. 

If the program returns  String,  then I can arrange this.
But with  (String, String),  I do not know how to do.
And in the real progam, it is a more complex labeled record, carried
along through the program.
Probably, the obstackle is in the very Haskell language.
Consider a simple example:

bottomStr :: String
bottomStr = let xs = xs in xs

bottomSPair :: (String, String)
bottomSPair = let p = p in p

bound = 10^8  :: Int   -- some large number

f1, f2, g1, g2 :: Char

f1 = head ('a' :  (if last [1 .. bound] > 0 then "b" else "c"))

f2 = head ('a' : bottomStr)

g1 = head $ fst $ addToSPair 'a'
     (if  last [1 .. bound] > 0  then ("b", "") else ("c", ""))

g2 = head $ fst $ addToSPair 'a' bottomSPair

addToSPair :: Char -> (String, String) -> (String, String)
addToSPair    c       (xs,     ys    ) =  (c:xs,   ys    )

main = putStr  [ f1,  '\n' ]
              -- f2
              -- g1, g2

g1 is similar to f1,  g2 similar to f2.

f1 and f2 are evaluated immediately to 'a';

g1 evaluates to 'a' after a long computation;
g2 evaluates to  Fail: <<loop>>

As g2 is similar to f2, should it have a value 'a' ?
   head $ fst $ addToSPair 'a' bottomSPair

bottomSPair  is of type  (String, String).
addToSPair   is declared as returning  (String, String).
Hence, the complier knows ab initio that after  addToSPair
the result is of kind
                      ('a': _,  _) :: (String, String)

Hence, applying further   head $ fst    yields  'a'.
This is in the air of a `lazy' computation.
In a more clear presentation, the computation should (?) be

   head $ fst $ addToSPair 'a' bottomSPair
   head $ fst $ addToSPair 'a' (bottomStr, bottomStr)
   head $ fst (`a':bottomStr, bottomStr)
   head (`a':bottomStr)

So, similarly as
              head ('a' : bottomStr)                    = 'a',   (1)
it should be
              head $ fst $ addToSPair 'a' bottomSPair   = 'a'    (2)

Probably, Haskell-98 does not put so. Right?

Question 1
What may be the consequences for the language 
(let us call it HCLazy)  if it treats the data constructors like in 
(2), like more `lazy' ones?

For example,  fst (bottom :: (a,b)) =  (bottom :: a)

Question 2
How to arrange the above `lazy' output?
The whole result story is ready in several hours, or days,
and each step should be displayed immediately as it is ready.

So far, I see no other way as to compile the program together with 
the  Trace  library, inserting there the calls
                            \ step ... -> trace (show step) $ ...

Thank you in advance for the explanations.

Copy, please, the answer to  mechvel at botik.ru

Serge Mechveliani
mechvel at botik.ru

More information about the Haskell mailing list