是否有可能生成和运行TemplateHaskell在运行时生成的代码?(Is it possible

2019-07-18 13:13发布

是否有可能生成和运行TemplateHaskell在运行时生成的代码?

使用C,在运行时,我可以:

  • 创建一个函数的源代码,
  • 调出的gcc将其编译到一个.so(Linux)的(或使用LLVM等),
  • 加载的.so和
  • 调用该函数。

是一个类似的事情可能与模板哈斯克尔?

Answer 1:

是的,这是可能的。 该GHC API将编译模板哈斯克尔。 一个证明的概念可在https://github.com/JohnLato/meta-th ,这虽然不是很复杂,表明即使提供类型安全些许的一个通用技术。 模板的Haskell表达式是生成使用Meta类型,则其可以被编译和加载到一个可用的功能。

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}

{-# OPTIONS_GHC -Wall #-}
module Data.Meta.Meta (
-- * Meta type
  Meta (..)

-- * Functions
, metaCompile
) where

import Language.Haskell.TH

import Data.Typeable as Typ
import Control.Exception (bracket)

import System.Plugins -- from plugins
import System.IO
import System.Directory

newtype Meta a = Meta { unMeta :: ExpQ }

-- | Super-dodgy for the moment, the Meta type should register the
-- imports it needs.
metaCompile :: forall a. Typeable a => Meta a -> IO (Either String a)
metaCompile (Meta expr) = do
  expr' <- runQ expr

  -- pretty-print the TH expression as source code to be compiled at
  -- run-time
  let interpStr = pprint expr'
      typeTypeRep = Typ.typeOf (undefined :: a)

  let opener = do
        (tfile, h) <- openTempFile "." "fooTmpFile.hs"
        hPutStr h (unlines
              [ "module TempMod where"
              , "import Prelude"
              , "import Language.Haskell.TH"
              , "import GHC.Num"
              , "import GHC.Base"
              , ""
              , "myFunc :: " ++ show typeTypeRep
              , "myFunc = " ++ interpStr] )
        hFlush h
        hClose h
        return tfile
  bracket opener removeFile $ \tfile -> do

      res <- make tfile ["-O2", "-ddump-simpl"]
      let ofile = case res of
                    MakeSuccess _ fp -> fp
                    MakeFailure errs -> error $ show errs
      print $ "loading from: " ++ show ofile
      r2 <- load (ofile) [] [] "myFunc"
      print "loaded"

      case r2 of
        LoadFailure er -> return (Left (show er))
        LoadSuccess _ (fn :: a) -> return $ Right fn

这个函数有一个ExpQ ,以及第一运行它在IO来创建纯Exp 。 的Exp然后适合打印到源代码,其被编译和在运行时加载的。 在实践中,我发现,更困难的障碍之一是指定在生成代码TH正确的进口。



Answer 2:

据我了解,你要创建并运行在运行时代码,我认为你可以使用做GHC API ,但我不是很确定你能达到什么范围。 如果你想要的东西像热交换代码,你可以看包热插拔 。



文章来源: Is it possible to generate and run TemplateHaskell generated code at runtime?