使用 GHC API 评估 Haskell 语句/表达式

发布于 2024-08-25 10:10:41 字数 613 浏览 11 评论 0原文

对于我正在编写的工具( http://hackage.haskell.org/package/explore )我需要一种在运行时读取 haskell 函数定义的方法,将它们应用于我的工具中的值并检索其应用程序的结果。

谁能给我一个使用 GHC(6.10.4 或 6.12.1)API 的非常基本的示例?

在运行时从文件中读取的示例函数定义:

f x = 10**(4/1102*x - 1)

预期的程序输出

--mapM_ print $ map f [428, 410, 389]
3.577165388142748
3.077536885227335
2.5821307011665815

!!UPDATE!!
我发布了一个快速答案,但它在执行目录中创建了一个目标文件,任何避免这种情况并避免所有文件 IO 的提示都是最受欢迎的。我还想看到一个在内存中执行所有操作的版本:例如,用户在 GUI 中提供函数定义,并且编译/评估不会创建任何目标文件。

For a tool I'm writing ( http://hackage.haskell.org/package/explore ) I need a way to read haskell function definitions at run-time, apply them to values from my tool and retrieve the results of their application.

Can anyone give me a very basic example using GHC (6.10.4 or 6.12.1) API?

example function definition to be read from a file at run-time:

f x = 10**(4/1102*x - 1)

expected program output

--mapM_ print $ map f [428, 410, 389]
3.577165388142748
3.077536885227335
2.5821307011665815

!!UPDATE!!

I posted a quick answer but it creates an object file in the directory of execution, any tips to avoid this and avoid all file IO is most welcome. I want to also see a version that does everything in memory: user provides the function definition in a GUI for example and the compilation / evaluation does not create any object files.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

_蜘蛛 2024-09-01 10:10:41

使用提示。它是 GHC API 的类似 GHCi 的包装器,使用起来并不困难。

如果您想要其使用示例,我在我的酸奶项目中使用它

Use hint. It's a GHCi-like wrapper around the GHC API that is not very difficult to use.

If you want an example of its use, I used it in my Yogurt project.

远昼 2024-09-01 10:10:41

改编自:http://www.bluishcoder。 co.nz/2008/11/dynamic-compilation-and-loading-of.html

f.hs:

module Func (Func.f) where

f :: Double -> Double
f x = 10**(4/1102*x - 1)

main.hs:

import GHC
import GHC.Paths
import DynFlags
import Unsafe.Coerce

import Control.Monad

main :: IO ()
main =
    defaultErrorHandler defaultDynFlags $ do
      func <- runGhc (Just libdir) $ do
        dflags <- getSessionDynFlags
        setSessionDynFlags dflags
        target <- guessTarget "f.hs" Nothing
        addTarget target
        r <- load LoadAllTargets
        case r of
          Failed -> error "Compilation failed"
          Succeeded -> do
            m <- findModule (mkModuleName "Func") Nothing
            setContext [] [m]
            value <- compileExpr ("Func.f")
            do let value' = (unsafeCoerce value) :: Double -> Double
               return value'
      let f = func
      mapM_ print $ map f [428, 410, 389]
      return ()

adapted from: http://www.bluishcoder.co.nz/2008/11/dynamic-compilation-and-loading-of.html

f.hs:

module Func (Func.f) where

f :: Double -> Double
f x = 10**(4/1102*x - 1)

main.hs:

import GHC
import GHC.Paths
import DynFlags
import Unsafe.Coerce

import Control.Monad

main :: IO ()
main =
    defaultErrorHandler defaultDynFlags $ do
      func <- runGhc (Just libdir) $ do
        dflags <- getSessionDynFlags
        setSessionDynFlags dflags
        target <- guessTarget "f.hs" Nothing
        addTarget target
        r <- load LoadAllTargets
        case r of
          Failed -> error "Compilation failed"
          Succeeded -> do
            m <- findModule (mkModuleName "Func") Nothing
            setContext [] [m]
            value <- compileExpr ("Func.f")
            do let value' = (unsafeCoerce value) :: Double -> Double
               return value'
      let f = func
      mapM_ print $ map f [428, 410, 389]
      return ()
余厌 2024-09-01 10:10:41

干得好,让 API 运行起来。我可以告诉您一些有关代码生成器如何工作的信息。

GHC 使用系统汇编器创建 .o 文件。如果没有可用的选项让 GHC 自行清理,那么您应该使用 http://hackage.haskell.org/trac/ghc/newticket?type=feature+request。为了提交请求,您需要注册一个帐户。

使用标准代码生成器,您将无法完全避免文件 I/O,只是因为 GHC 将创建可重定位目标代码的工作委托给汇编器。有一个基于 LLVM 的实验性后端,可能能够在内存中完成所有操作,但如果它在 6.13 之前的版本中可用,我会感到惊讶。然而,在 GHC 开发者名单上可能值得询问。

Nice work getting the API going. I can tell you a little bit about how the code generator works.

GHC uses the system assembler to create a .o file. If there is not an option available to get GHC to clean up after itself, then you should file a feature request against the API, using the bug tracker at http://hackage.haskell.org/trac/ghc/newticket?type=feature+request. In order to file the request, you will need to register an account.

Using the standard code generator, you will not be able to avoid file I/O entirely, just because GHC delegates the work of creating relocatable object code to the assembler. There is an experimental back end based on LLVM that might be able to do everything in memory, but I would be surprised if it is available in anything earlier than 6.13. However it could be worth asking on the GHC developers' list.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文