Haskell GHC API错误中的动态编译

Cra*_*nes 7 compiler-construction api haskell dynamic-compilation ghc

我一直在尝试使用GHC API进行一些基本的动态代码编译,遵循此处的教程.

这段代码:

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

main :: IO ()
main =
    defaultErrorHandler defaultDynFlags $ do
      func <- runGhc (Just libdir) $ do
        dflags <- getSessionDynFlags
        setSessionDynFlags dflags
        target <- guessTarget "Test.hs" Nothing
        addTarget target
        r <- load LoadAllTargets
        case r of
          Failed -> error "Compilation failed"
          Succeeded -> do
            m <- findModule (mkModuleName "Test") Nothing
            setContext [] [m]
            value <- compileExpr ("Test.print")
            do let value' = (unsafeCoerce value) :: String -> IO ()
               return value'
      func "Hello"
      return ()
Run Code Online (Sandbox Code Playgroud)

应从另一个名为Test.hs的文件中获取print函数,加载它并运行其print函数.

我使用以下命令使用ghc版本7.4.1编译代码:

ghc -package ghc --make Api.hs
Run Code Online (Sandbox Code Playgroud)

但是收到以下错误:

Api.hs:8:25:
    Couldn't match expected type `Severity' with actual type `Settings'
    Expected type: LogAction
      Actual type: Settings -> DynFlags
    In the first argument of `defaultErrorHandler', namely
      `defaultDynFlags'
    In the expression: defaultErrorHandler defaultDynFlags
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?我已经检查了GHC API文档但是我对这种事情的理解还不够深入.

Dan*_*her 6

该教程已过时.在ghc-7.0.*和之前,类型defaultErorHandler

defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => DynFlags -> m a -> m a
Run Code Online (Sandbox Code Playgroud)

而且defaultDynFlags只是一个价值.

截至ghc-7.2.*,类型defaultErrorHandler

defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => LogAction -> m a -> m a
Run Code Online (Sandbox Code Playgroud)

defaultDynFlags 是一个功能

defaultDynFlags :: Settings -> DynFlags
Run Code Online (Sandbox Code Playgroud)

并且LogAction是同义词

type LogAction = Severity -> SrcSpan -> PprStyle -> Message -> IO ()
Run Code Online (Sandbox Code Playgroud)

在7.6,它已经改变了,我们现在有了

defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => FatalMessager -> FlushOut -> m a -> m a
Run Code Online (Sandbox Code Playgroud)

type FatalMessager = String -> IO ()
Run Code Online (Sandbox Code Playgroud)

FlushOut成为一个newtype包装IO ().

我不太熟悉GHC Api(对我而言是一个过快的目标),所以我不确定工作代码应该是什么样子,但对于7.2和7.4系列,第一个参数defaultErrorHandler应该是defaultLogAction.

另外的类型setContext发生了变化,我不知道如果我有什么你想要做什么,但它编译(7.4.2,但你还需要ghc-paths包除了ghcGHC.Paths模块) -我还没有尝试然而,跑吧.

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

main :: IO ()
main =
    defaultErrorHandler defaultLogAction $ do
      func <- runGhc (Just libdir) $ do
        dflags <- getSessionDynFlags
        setSessionDynFlags dflags
        target <- guessTarget "Test.hs" Nothing
        addTarget target
        r <- load LoadAllTargets
        case r of
          Failed -> error "Compilation failed"
          Succeeded -> do
            m <- findModule (mkModuleName "Test") Nothing
            setContext [IIModule m]
            value <- compileExpr ("Test.print")
            do let value' = (unsafeCoerce value) :: String -> IO ()
               return value'
      func "Hello"
      return ()
Run Code Online (Sandbox Code Playgroud)