{-# LANGUAGE CPP #-} -- | A compat module to take fixed points in 'Q'. module TH.FixQ (fixQ) where #if MIN_VERSION_template_haskell(2,17,0) import Control.Monad.Fix (mfix) import Language.Haskell.TH.Syntax (Q (..)) fixQ :: (a -> Q a) -> Q a fixQ = mfix #else -- We don't have a MonadFix instance for Q import Control.Concurrent.MVar (newEmptyMVar, readMVar, putMVar) import Control.Exception (BlockedIndefinitelyOnMVar (..), catch, throwIO) import Control.Exception.Base (FixIOException (..)) import Language.Haskell.TH.Syntax (Q (..), runIO) import GHC.IO.Unsafe (unsafeDupableInterleaveIO) fixQ :: (a -> Q a) -> Q a fixQ k = do m <- runIO newEmptyMVar ans <- runIO (unsafeDupableInterleaveIO (readMVar m `catch` \BlockedIndefinitelyOnMVar -> throwIO FixIOException)) result <- k ans runIO (putMVar m result) return result #endif