Skip to content

Internal and external interpreter differ in interaction between putQ and recover

Take the following sample program. This places a value of "0" into the TH state. Then within a recover block it places a value of "42" there, and then immediately errors.

We then lift whatever the current value in the store is.

{-# LANGUAGE TemplateHaskell #-}

import Language.Haskell.TH.Syntax
main = print $(putQ "0" >> recover (pure ()) (putQ "42" >> fail "oops")  >> getQ @String >>= lift )

There are two reasonable answers to what this program should print. It will print 0 if we roll back state when we recover from an error (This is how the external interpreter handles it). We will print 42 if we do not rollback state (this is how the internal interpreter handles it`

We get different answers whether we run with the internal or external interpreter.

ghc on  wip/abstract-q [$!?] via λ 9.10.1 via  via ❄️  impure (ghc-shell-for-ghc-buildenv-9.13-0-env) 
❯ ghc Test.hs -fforce-recomp -fexternal-interpreter && ./Test
[1 of 2] Compiling Main             ( Test.hs, Test.o )
[2 of 2] Linking Test [Objects changed]
Just "0"

ghc on  wip/abstract-q [$!?] via λ 9.10.1 via  via ❄️  impure (ghc-shell-for-ghc-buildenv-9.13-0-env) 
❯ ghc Test.hs -fforce-recomp && ./Test
[1 of 2] Compiling Main             ( Test.hs, Test.o )
[2 of 2] Linking Test [Objects changed]
Just "42"

We should pick one of these semantics and stick with it!

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information