0

I have this pSizeOf function which takes a type param and returns the size of that type as type-level literal:

import Foreign.Storable
import Language.Haskell.TH
import qualified Data.Kind as K

pSizeOf :: forall (t :: K.Type). (Storable t) => TypeQ
pSizeOf = pure $ LitT $ NumTyLit $ fromIntegral $ sizeOf (undefined :: t)

I wonder is it possible to rewrite it without using type param t, something of type

pSizeOf :: Name -> TypeQ

How can I get undefined of that type from Name? The following code:

pSizeOf :: Name -> TypeQ
pSizeOf n = pure $ LitT $ NumTyLit $ fromIntegral $ sizeOf $( SigE (VarE 'undefined) (ConT n))

fails with error:

    * GHC stage restriction:
        `n' is used in a top-level splice, quasi-quote, or annotation,
        and must be imported, not defined locally
    * In the untyped splice: $(SigE (VarE 'undefined) (ConT n))
Alexey Vagarenko
  • 1,206
  • 8
  • 15
  • 2
    You can't define a TH operation and use it in the same file, you need to make a separate module. – Thomas M. DuBuisson Oct 30 '17 at 14:25
  • 1
    The stage restriction here applies to the local binding `n`, not to a top-level function, so moving the function to a different file won't help. The best you can do is to have a nested splice - something like `pSizeOf n = [| pure $ LitT $ NumTyLit $ fromIntegral $ sizeOf (undefined :: $(conT n)) |]`. Then you can write e.g. `type T = $($(pSizeOf ''Int))` – user2407038 Oct 30 '17 at 16:53

0 Answers0