(Creating a new thread from State monad - memory exhausted - #27 by doyougnu)
Hi @doyougnu, I wonder if you could help me with something. I have been trying to understand cases where
Unlifted has benefits above and beyond Make invalid laziness unrepresentable (MILU). As I mentioned in an earlier comment,
nothunks was what originally prompted me to develop the idea of MILU, and achieve a type level guarantee that a value contains no thunks. For
Lifted types MILU doesn’t quite imply no thunks, because the value itself may be a thunk! It just implies that once the value is forced it no longer contains any thunks.
Of course, using
Unlifted types appropriately can be part of MILU. But I still don’t understand specific cases where using
Unlifted types provides more of a benefit than MILU with
Lifted types. Do you have any examples?
Something I’ve been wondering about is whether GHC can take advantage of strictness of return types of functions. For example, if I have a function
strictDup !x = (x, x)
can GHC take advantage of the fact that the fields of the tuple are already evaluated after the pair constructor is evaluated? For example, can it avoid an evaluation in
let (y, z) = strictDup x in y + z
From looking at the core, or even the STG, I don’t think so. It still converts to the following:
let (y, z) = strictDup x
in case y of Int# y' ->
case z of Int# z' ->
Int# y' z'
and I think the pattern match on
Int# requires an attempt at evaluation. In fact I don’t see any way to pattern match in Core or STG without attempting an evaluation too! As far as I can tell, the same holds even for
data StrictPair x y = StrictPair !x !y
strictPair' x = StrictPair x x
StrictPair were defined to have two
Unlifted components then I think the evaluation could in principle be avoided, but again I don’t know if GHC’s intermediate representations are rich enough to express that.
Does anyone have any insight they can share?