It is. 

However that doesn't give users the ability to solve this since -ffull-lazines allows GHC to potentially turn such a function into a thunk.
One can disable full-laziness to avoid this, but you might like some things to be floated/shared and others to be constrained to a certain context rather than retaining them.

Even if GHC would leave the function itself one might end up with code like:

foo :: Void# -> T
foo = ...
bar x y z =
    let r = foo void#
    in (f r,f r)

Now foo itself is a "non-updatable thunk". But we capture it's result in an updatable thunk.
Hence the need for the non-updatable attribute to be transitive in some fashion.
Associating it with the return type might be one solution to address this.



On 03/02/2026 13:34, Tom Ellis via ghc-devs wrote:
Isn't a function of type `(# #) -> T` already (isomorphic to) a
"non-updatable thunk" of type T?

Tom

On Tue, Feb 03, 2026 at 11:43:48AM +0000, Simon Peyton Jones via ghc-devs wrote:
Hmm.  So your proposal is:

   - When declaring a type T, specify it as a "non-updatable type"
   - A thunk of type T is call-by-name

On Tue, 3 Feb 2026 at 08:25, Edsko de Vries <edsko@well-typed.com> wrote:
I think there *is* a better answer: I think (but this will require
careful consideration) that the way is is to be able to mark certain types
as "never update thunks of this type".
_______________________________________________
ghc-devs mailing list -- ghc-devs@haskell.org
To unsubscribe send an email to ghc-devs-leave@haskell.org