Why no exposed `NullAddr#` literal?
Suppose that, switching on -XDataKinds -XGADTSyntax -XKindSignatures -XMagicHash -XUnliftedNewtypes and importing the relevant definitions from GHC.Exts, one creates the newtype
newtype MyAddr# :: TYPE AddrRep where
WrapAddr# :: Addr# -> MyAddr#
(perhaps because they wish to signal interaction with a particular, trusted subset of foreign code—I think this is not a wholly unreasonable thing to do). Then they might like to declare something along the lines of
myNullAddr# :: MyAddr#
myNullAddr# = WrapAddr# nullAddr#
but this is of course disallowed, being an unlifted top-level binding. Fair enough!
The next best thing (actually, the ostensibly better thing, seeing as GHC already internally seems to treat nullAddr# as a literal —cf. LitNullAddr defined in compiler/GHC/Types/Literal.hs, but I am admittedly not very familiar with the GHC codebase) would be to be turn on -XPatternSynonyms and write
pattern MyNullAddr# :: MyAddr#
pattern MyNullAddr# = WrapAddr# _
where the hole is filled by some literal coinciding in value with nullAddr#. Indeed, were such a literal available, I don’t see why it wouldn’t make sense to deprecate the current nullAddr# in its favor, much like the old void# was deprecated in favor of (# #).
Unfortunately, such a literal does not seem to be available, neither via -XExtendedLiterals nor by using -XTemplateHaskell to splice some constructor of Lit from Language.Haskell.TH. (Per error GHC-65904, the interaction between the two extensions does not yet seem fully fleshed out.)
Is there any fundamental obstruction to GHC exposing such a literal? I tried searching for prior discussion about this matter but came up empty-handed.
Edit: I should add that the best workaround of which I’m currently aware is to use the standard top-level-unlifted-value binding trick
myNullAddr# :: (# #) -> MyAddr#
myNullAddr# = \ _ -> WrapAddr# nullAddr#
It might not be abominable, but it sure doesn’t spark any joy…
Discussion in the ATmosphere