Serge D. Mechveliani mechvel at botik.ru
Wed Oct 20 05:47:46 EDT 2004

```Dear Haskellers,

I am still trying to find out how to organize naturally a
`lazy' printing of an accumulated data field.

People advised me  no-buffering  and also the  tilde  usage.
But there is some more obstackle.

The `trace' is accumulated in  fl1  by repeating  consD,
where

data D = D {fl1 :: String, fl2 :: String}

consD :: Char -> D -> D
consD    a       d =  d {fl1 = a:(fl1 d)}

(tilde is not needed here?)

The whole process computes  res :: D  in a certain complex
recursive manner. One of the ways to use  res  is to print out
the `trace' field:
let  res = (complexProcess ...)  :: D
in
show \$ fl1 res

I need  fl1 res  to be formed `lazily'.
For example,
take 2 \$ fl1 res   may be ready (and shown) immediately,
and          last   \$ fl1 res   may be ready long after.

If it was  [Char]  istead of  D,  then this would be easy.
Because
head \$ (a:) xs  =  a

For example,       head \$ ('a':) \$ (error "")  =  'a'

But is this true for  consD and headD, where

?
That is    headD \$ consD a res  =?=  a

If  res  is not a bottom,  then, yes.
Right?
And if  res  occurs, say,  (error ""),  then  consD  cannot intrude
into  fl1 res,  and the whole expression has a value _|_.
Right?
So, generally,  headD \$ consD a res  is not equivalent to  a;
hence the head members of  fl1 res  have to wait at least until it
becomes clear that  res  is not a bottom.
Right?

So far, I see the two way-outs.

1. To insert the usage of the `trace' tool
-- which does not look nice.

2. To have a result   res :: [D]  instead of D.

And as soon as a new  step  appears, form  res ++[d {fl1 = [step]}]
where
d = last res,
fl2 also can be modified.
Now,                        map fl1 res

is the needed trace, which, I believe, would be formed `lazily'.

I wonder
a) whether there is a nicer solution,

b) what happens if the Language treats the constructors as the
homomorphisms.
For example,      head \$ (a:) xs  =  a
==>
head \$ fl1 \$ D {fl1 = (a:) fl1}  =  a

Here  (D, fl1)  is a constructor, and its insertion between
the functions  head  and  (a:)  preserves the above relation
between them
(is this called `bottom chasing' ?).
Probably, this will eliminate unneeded strictness -- ?

Thank you in advance for the explanations.