Skip to content

Instantly share code, notes, and snippets.

@ramirez7
Last active January 11, 2024 19:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ramirez7/4742eacdfae0588cd100bfb07e124131 to your computer and use it in GitHub Desktop.
Save ramirez7/4742eacdfae0588cd100bfb07e124131 to your computer and use it in GitHub Desktop.
ghci command to run top-level TH. Thanks /u/affinehyperplane for the trick! https://www.reddit.com/r/haskell/comments/18vkivp/comment/kh9byjd/?utm_source=reddit&utm_medium=web2x&context=3
:{
let doTH code = do
u <- Data.Unique.newUnique
let decls = "ghciTH_" ++ show (Data.Unique.hashUnique u)
pure $ unlines
[ unwords ["let", decls, "=", code]
, "() = ();" ++ decls
]
:}
:def th doTH
@ramirez7
Copy link
Author

Example usage (to inspect an apecs world):

λ :script ./th-ghci
λ :seti -XTemplateHaskell -XFlexibleInstances -XMultiParamTypeClasses
λ import Apecs
λ :th makeWorldAndComponents "World" []
λ :i World
type World :: *
data World
  = World {rec_6989586621679020007 :: !(Storage EntityCounter)}
        -- Defined at <interactive>:5:9
instance [safe] Monad m => Has World m EntityCounter
  -- Defined at <interactive>:5:9

@ramirez7
Copy link
Author

Note that if there's an error in the code you pass to :th, it'll print the error and then a spurious error regarding ghciTH_XXX not being in scope:

λ :th makeWorldAndComponents "World" []

<interactive>:3:16: error:
    Variable not in scope:
      makeWorldAndComponents :: String -> [a0] -> t

<interactive>:3:9: error:
    Variable not in scope:
      ghciTH_1 :: Language.Haskell.TH.Lib.Internal.DecsQ

(I forgot to import Apecs in the above example)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment