我正在开发一个分析Haskell代码的项目.我决定使用GHC来解析源代码并推断类型而不是编写我自己的代码来做到这一点.现在,我正在通过Haddock文档,但它进展缓慢.有谁知道一个很好的教程?
编辑:澄清一下,我不是在寻找像hlint这样的东西.我正在编写自己的工具来分析Haskell代码的运行时特性,所以就像我正在编写一个不同的hlint.我正在寻找的基本上是维基页面GHC作为一个库的扩展.
我有一个现有的Haskell函数,它使用GHC API动态加载模块中的编译代码.它基于Haskell博客文章动态编译和模块加载的代码.
代码在GHC 7.0中运行良好,但必须稍加修改才能在GHC 7.2中编译,因为GHC API发生了变化.
代码现在在GHC 7.2中引发运行时错误:
mkTopLevEnv: not a home module (module name):(function name)
Run Code Online (Sandbox Code Playgroud)
代码是
evalfuncLoadFFI String moduleName,
String externalFuncName,
String internalFuncName = do
result <- liftIO $ defaultRunGhc $ do
dynflags <- GHC.getSessionDynFlags
_ <- GHC.setSessionDynFlags dynflags
m <- GHC.findModule (GHC.mkModuleName moduleName) Nothing
--------------------------------------------------------
-- The following code works fine in GHC 7.0.4:
--
-- GHC.setContext [] [(m, Nothing)]
--
-- This new code attempts to set context to the module,
-- but …
Run Code Online (Sandbox Code Playgroud) 对于我正在编写的工具(http://hackage.haskell.org/package/explore),我需要一种在运行时读取haskell函数定义的方法,将它们应用于我的工具中的值并检索其应用程序的结果.
任何人都可以使用GHC(6.10.4或6.12.1)API给我一个非常基本的例子吗?
要在运行时从文件中读取的示例函数定义:
f x = 10**(4/1102*x - 1)
Run Code Online (Sandbox Code Playgroud)
预期的计划产出
--mapM_ print $ map f [428, 410, 389]
3.577165388142748
3.077536885227335
2.5821307011665815
Run Code Online (Sandbox Code Playgroud)
!! UPDATE!
我发布了一个快速回答,但它在执行目录中创建了一个目标文件,任何提示都可以避免这种情况并避免使用所有文件IO.我还希望看到一个在内存中执行所有操作的版本:例如,用户在GUI中提供函数定义,编译/评估不会创建任何目标文件.
想法
你好!我想创建一个程序,它将生成Haskell Core并将使用GHC API将其进一步编译成可执行文件.但在我做之前,我想构建一个非常基本的例子,展示我们如何才能将Haskell源代码编译成CORE然后再编译成二进制文件.
问题
我已经阅读了很多文档并尝试了GHC Api的许多方法,但是现在没有成功.我开始使用官方GHC Api介绍并成功编译了这些示例.实例显示下列函数的用法:parseModule
,typecheckModule
,desugarModule
,getNamesInScope
和getModuleGraph
,但不包括最后的编译步骤.另一方面,api中有一些函数,其名称与问题相关,如HscMain.{hscCompileOneShot,hscCompileBatch}或GHC.{compileToCoreModule,compileCoreToObj}.我尝试使用它们,但是我遇到了运行时错误,就像在这个例子中一样:
import GHC
import GHC.Paths ( libdir )
import DynFlags
targetFile = "Test.hs"
main :: IO ()
main = do
res <- example
return ()
example =
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do
runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
let dflags' = foldl xopt_set dflags
[Opt_Cpp, Opt_ImplicitPrelude, Opt_MagicHash]
setSessionDynFlags dflags'
coreMod <- compileToCoreModule targetFile
compileCoreToObj False …
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用GHC API动态编译和加载Haskell模块.我理解API从一个版本到另一个版本的波动很大,所以我特别谈到GHC 7.6.*.
我试过在MacOS和Linux上运行相同的代码.在这两种情况下,插件模块都可以正常编译,但在加载时会出现以下错误:Cannot add module Plugin to context: not interpreted
问题类似于本文中的问题,只有在主机程序的同一运行中编译模块时才会加载该问题.
-- Host.hs: compile with ghc-7.6.*
-- $ ghc -package ghc -package ghc-paths Host.hs
-- Needs Plugin.hs in the same directory.
module Main where
import GHC
import GHC.Paths ( libdir )
import DynFlags
import Unsafe.Coerce
main :: IO ()
main =
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do
result <- runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
setSessionDynFlags dflags
target <- guessTarget "Plugin.hs" Nothing
setTargets [target]
r …
Run Code Online (Sandbox Code Playgroud) 我需要有类似的东西
-- Main.hs
module Main where
main :: IO ()
main = do
<import Plugin>
print Plugin.computation
Run Code Online (Sandbox Code Playgroud)
有插件就好
-- Plugin.hs
module Plugin where
computation :: Int
computation = 4
Run Code Online (Sandbox Code Playgroud)
但是,我需要将插件与主应用程序一起编译.他们需要一起部署.只有模块的导入(而不是编译)才能动态发生.
我发现动态加载已编译的Haskell模块 - GHC 7.6,它在GHC 8.0.2中运行得很好,除了它在执行应用程序时需要插件的源文件在当前工作目录中.
是否可以使用GHC API从String而不是文件加载模块?http://hackage.haskell.org/package/ghc-8.2.1/docs/GHC.html#t:Target表明这是可能的,但文档有很多漏洞,我找不到实际做到这一点的方法.如果可以实现,我可以使用file-embed将插件源文件包含到已编译的二进制文件中.例:
module Main where
-- Dynamic loading of modules
import GHC
import GHC.Paths ( libdir )
import DynFlags
import Unsafe.Coerce
import Data.Time.Clock (getCurrentTime)
import StringBuffer
pluginModuleNameStr :: String
pluginModuleNameStr = "MyPlugin"
pluginSourceStr :: String
pluginSourceStr = unlines …
Run Code Online (Sandbox Code Playgroud) 我想通过捎带进入GHC编译过程并改变其核心表示来测试实现编译器优化.想法是有类似的东西:
runGhc (Just libdir) $ do
...
c <- compileToCoreModule targetFile
compileCoreToObj False (modify c)
...
Run Code Online (Sandbox Code Playgroud)
其中modify
采用Core表示并返回修改后的版本.但是,这段代码失败了(即使修改什么也没做),但是没有非常有用的消息:
expectJust mkStubPaths
Run Code Online (Sandbox Code Playgroud)
关于如何使这项工作的任何想法,或者甚至可能以这种方式实现代码转换?
我想在Windows上部署需要访问GHC API的应用程序.使用Wiki中的第一个简单示例:
http://www.haskell.org/haskellwiki/GHC/As_a_library
导致以下错误(在具有haskell平台的一台机器上编译并在另一个干净的Windows安装上执行):test.exe:在C:\ haskell\lib\package.conf.d中找不到包数据库
我想将我的应用程序部署为一个简单的zip文件,而不是要求用户安装任何东西.是否有一种简单的方法可以在该zip文件中包含所需的GHC内容,以便它可以工作?
假设我有一个任意模块
module Foo where
foo :: Moo -> Goo
bar :: Car -> Far
baz :: Can -> Haz
Run Code Online (Sandbox Code Playgroud)
在哪里foo
,bar
和baz
,正确实施等
我想将此模块重新生成为自动生成的数据类型和相应的对象:
import Foo (Moo, Goo, Car, Far, Can, Haz)
import qualified Foo
data FooModule = Foo
{ foo :: Moo -> Goo
, bar :: Car -> Far
, baz :: Can -> Haz
}
_Foo_ = Foo
{ foo = Foo.foo
, bar = Foo.bar
, baz = Foo.baz
}
Run Code Online (Sandbox Code Playgroud)
名称必须与原始模块完全相同.
我可以手动执行此操作,但这非常繁琐,所以我想编写一些代码来为我执行此任务.
我不确定如何处理这样的任务.Template …
我需要一种(快速和脏的)方法来获得一个以字符串形式给出的Haskell表达式的表示.
我目前看到3个选项:
我甚至不需要一个完整的解决方案,因为可以输入一个合理的Haskell基本子集的库/工具就足够了.
那么实现这一目标的最简单方法是什么?
ghc-api ×10
haskell ×10
ghc ×7
module ×2
compilation ×1
deployment ×1
evaluation ×1
runtime ×1
windows ×1