{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreib33b47snwczelg7lgfpfq55gebvsnvfm4sskv7gsqthk37viqfom",
"uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mmtmsmzzjrr2"
},
"path": "/t/why-no-exposed-nulladdr-literal/14157#post_5",
"publishedAt": "2026-05-27T13:11:56.000Z",
"site": "https://discourse.haskell.org",
"tags": [
"@jaror"
],
"textContent": "jaror:\n\n> TIL pattern synonyms can be unlifted. But then a bidirectional pattern should work:\n>\n>\n> pattern MyNullAddr# :: MyAddr#\n> pattern MyNullAddr# <- ((\\(WrapAddr# x) -> eqAddr# nullAddr# x) -> 1#) where\n> MyNullAddr# = WrapAddr# nullAddr#\n>\n\nAwesome, thanks! This does spark joy.\n\ntomjaguarpaw:\n\n> I’m not sure it is fair, or at least there could in principle be an exception for values, and a newtype constructor applied to a value would be value. Maybe that adds too much extra complexity to be worth it.\n\nMy impression is that on the frontend (so more superficially than @jaror’s work above, but also more programmer-visibly) and with the exception of the `nullAddr#` issue, a statically-known fully evaluated unlifted value should be able to be built up from literals and constructors, hence should be bindable as an implicitly bidirectional unlifted pattern synonym. `Language.Haskell.TH.Lit` already represents literals of types `Int#`, `Word#`, `Char#`, `Float#`, and `Double#` (and hopefully once `-XExtendedLiterals` is fully supported by TemplateHaskell, also `Int8#`, `Int16#`, `Int32#`, `Int64#`, `Word8#`, `Word16#`, `Word32#`, and `Word64#`—maybe even eventually SIMD literals, although those aren’t currently supported by `-XExtendedLiterals` either), so in cases where the literal value is the result of a nontrivial computation one can do something like\n\n\n {-# LANGUAGE Haskell2010 #-}\n\n module MyInt.TH where\n\n {- | Here because of the stage restriction -}\n complicated :: Integer -> Integer\n complicated = \\ n -> product [ 1 .. n ]\n\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n {-# LANGUAGE Haskell2010\n , GADTSyntax\n , MagicHash\n , PatternSynonyms\n , UnliftedNewtypes\n , TemplateHaskell\n #-}\n\n module MyInt where\n\n import GHC.Exts\n import Language.Haskell.TH\n import MyInt.TH\n\n newtype MyInt# where\n WrapInt# :: Int# -> MyInt#\n\n data MyInt where\n MyI# :: Int# -> MyInt\n\n {- | Binds 'WrapInt# 2432902008176640000#' as a pattern -}\n $(pure $\n let nm = mkName \"Fac20Int#\"\n n = complicated 20\n in [ PatSynD\n ( nm )\n ( PrefixPatSyn [ ] )\n ( ImplBidir )\n ( ConP\n ( 'WrapInt# )\n [ ]\n [ LitP ( IntPrimL n ) ] )\n , PatSynSigD\n ( nm )\n ( ConT ''MyInt# ) ]\n )\n\n {- | Binds 'MyI# 2432902008176640000#' as a value -}\n fac20Int :: MyInt\n fac20Int = $(pure $\n let n = complicated 20\n in AppE\n ( ConE 'MyI# )\n ( LitE ( IntPrimL n ) )\n )\n\n",
"title": "Why no exposed `NullAddr#` literal?"
}