是否有可能生成并运行TemplateHaskell产生code运行时? [英] Is it possible to generate and run TemplateHaskell generated code at runtime?
问题描述
是否有可能生成并运行TemplateHaskell产生code运行时?
Is it possible to generate and run TemplateHaskell generated code at runtime?
使用C,在运行时,我可以:
Using C, at runtime, I can:
- 创建一个函数的源代码code,
- 调出的gcc来编译成一个.so(Linux版)(或使用LLVM等),
- 加载的.so和
- 调用该函数。
是一个类似的事情可能与模板哈斯克尔?
Is a similar thing possible with Template Haskell?
推荐答案
是的,这是可能的。该GHC API将编译模板哈斯克尔。一个证明的概念,请 https://github.com/JohnLato/meta-th ,其中,虽然不是非常复杂的,表明即使提供类型安全些许的一个总的技术。模板哈斯克尔前pressions正在建立一个使用元
键入,然后可以编译和加载到可用的功能。
Yes, it's possible. The GHC API will compile Template Haskell. A proof-of-concept is available at https://github.com/JohnLato/meta-th, which, although not very sophisticated, shows one general technique that even provides a modicum of type safety. Template Haskell expressions are build using the Meta
type, which can then be compiled and loaded into a usable function.
{-# 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来创建一个纯精通
。在精通
然后pretty印制成源$ C $ C,这是编译和运行时加载。在实践中,我发现,更困难的障碍之一是指定在生成的TH code正确的进口。
This function takes an ExpQ
, and first runs it in IO to create a plain Exp
. The Exp
is then pretty-printed into source code, which is compiled and loaded at run-time. In practice, I've found that one of the more difficult obstacles is specifying the correct imports in the generated TH code.
这篇关于是否有可能生成并运行TemplateHaskell产生code运行时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!