Forced strictness for lists in haskell
Asked Answered
R

2

11

I made really time consuming algorithm which produces a short string as the result. When I try to print it (via putStrLn) it appears on the screen character by character. I did understand why that happened, and I tried to force evaluation of the string before actual printing.

myPrint !str = putStrLn str

But this help very little. When I ran the program in debug I noticed that the !str forced evaluation only for the first character.

Does anyone know why is that, and how to deal with this?

Recalesce answered 5/4, 2011 at 20:23 Comment(2)
What is your problem with char-per-char printing? I like this approach, as you can see, when the program will evaluate your stuff.Deniable
This is gonna be a tool, it just looks a bit ugly. But for debugging purposes I completely agree, it might be useful.Recalesce
F
16

(!) translates into seq, which evaluates strictly to Weak Head Normal Form -- that is, it only evaluates to the outermost constructor. To evaluate more deeply, you need a "deep" form of seq.

This is known as deepseq.

It is in the deepseq package.

Fresco answered 5/4, 2011 at 20:27 Comment(2)
To clarify, for lists, the "outermost constructor" is the leftmost :, which explains why it forces only the first character of the string.Nought
A bit netter illustration of what is Weak Head Normal Form is hereRecalesce
C
2
seqList :: [a] -> ()
seqList [] = ()
seqList (x:xs) = strictList xs
Carnauba answered 6/4, 2011 at 7:7 Comment(3)
This will sort of work, but only if you actually require the () to be evaluated, e.g. seq (seqList xs) (doSomethingWith xs). Even then, it will only force the spine of the list, not the individual elements (not that just forcing the spine isn't useful). It can be tricky to get strictness correct!Robbyrobbyn
Also, I think you mean seqList in the last line.Robbyrobbyn
Another way is to perform some useless computations on the list: length $ filter (=="?") list.Deniable

© 2022 - 2024 — McMap. All rights reserved.