Динамическая загрузка скомпилированного модуля Haskell - GHC 7.6

Я пытаюсь динамически компилировать и загружать модули Haskell, используя GHC API. Я понимаю, что API сильно колеблется от одной версии к другой, поэтому я специально говорю о GHC 7.6.*.

Я попытался запустить один и тот же код на MacOS и Linux. В обоих случаях модуль Plugin компилируется нормально, но выдает следующую ошибку при загрузке: 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 <- load LoadAllTargets
        case r of
          Failed    -> error "Compilation failed"
          Succeeded -> do
            setContext [IIModule (mkModuleName "Plugin")]
            result <- compileExpr ("Plugin.getInt")
            let result' = unsafeCoerce result :: Int
            return result'
      print result

И плагин:

-- Plugin.hs
module Plugin where

getInt :: Int
getInt = 33

1 ответ

Решение

Проблема в том, что вы используете IIModule, Это указывает на то, что вы хотите перенести модуль и все в нем, включая неэкспортированные данные, в контекст. Это по сути так же, как :load со звездочкой в ​​GHCi. И, как вы заметили, это работает только с интерпретированным кодом, поскольку позволяет вам "заглянуть внутрь" модуля.

Но это не то, что вам нужно здесь. То, что вы хотите, это загрузить его, как если бы вы использовали :module или import декларация, которая работает с скомпилированными модулями. Для этого вы используете IIDecl который принимает декларацию импорта, которую вы можете сделать с simpleImportDecl:

setContext [IIDecl $ simpleImportDecl (mkModuleName "Plugin")]
Другие вопросы по тегам