Why no exposed `NullAddr#` literal?
jaror:
TIL pattern synonyms can be unlifted. But then a bidirectional pattern should work:
pattern MyNullAddr# :: MyAddr# pattern MyNullAddr# <- ((\(WrapAddr# x) -> eqAddr# nullAddr# x) -> 1#) where MyNullAddr# = WrapAddr# nullAddr#
Awesome, thanks! This does spark joy.
tomjaguarpaw:
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.
My 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
{-# LANGUAGE Haskell2010 #-}
module MyInt.TH where
{- | Here because of the stage restriction -}
complicated :: Integer -> Integer
complicated = \ n -> product [ 1 .. n ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{-# LANGUAGE Haskell2010
, GADTSyntax
, MagicHash
, PatternSynonyms
, UnliftedNewtypes
, TemplateHaskell
#-}
module MyInt where
import GHC.Exts
import Language.Haskell.TH
import MyInt.TH
newtype MyInt# where
WrapInt# :: Int# -> MyInt#
data MyInt where
MyI# :: Int# -> MyInt
{- | Binds 'WrapInt# 2432902008176640000#' as a pattern -}
$(pure $
let nm = mkName "Fac20Int#"
n = complicated 20
in [ PatSynD
( nm )
( PrefixPatSyn [ ] )
( ImplBidir )
( ConP
( 'WrapInt# )
[ ]
[ LitP ( IntPrimL n ) ] )
, PatSynSigD
( nm )
( ConT ''MyInt# ) ]
)
{- | Binds 'MyI# 2432902008176640000#' as a value -}
fac20Int :: MyInt
fac20Int = $(pure $
let n = complicated 20
in AppE
( ConE 'MyI# )
( LitE ( IntPrimL n ) )
)
Discussion in the ATmosphere