首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否可以在运行时生成和运行TemplateHaskell生成的代码?

是否可以在运行时生成和运行TemplateHaskell生成的代码?
EN

Stack Overflow用户
提问于 2013-01-22 13:22:32
回答 2查看 614关注 0票数 10

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

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

  • 创建函数的源代码,
  • 请gcc将其编译为.so (或使用llvm等),
  • 加载.so和
  • 打电话给函数。

模板Haskell也有类似的可能吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-22 13:49:47

是的,有可能。GHC将编译模板Haskell。https://github.com/JohnLato/meta-th提供了一个概念的证明,虽然不是很复杂,但它展示了一种通用的技术,甚至提供了少量的类型安全性。模板Haskell表达式使用Meta类型构建,然后可以编译并加载到一个可用的函数中。

代码语言:javascript
运行
复制
{-# 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代码中指定正确的导入。

票数 14
EN

Stack Overflow用户

发布于 2013-01-22 13:26:47

据我所知,您希望在运行时创建和运行代码,我认为可以使用GHC API来完成,但我不太确定您可以实现什么。如果您想要像热代码交换之类的东西,可以查看包热浪

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14459577

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档