7

ここにあるチュートリアルに従って、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 ()

Test.hs という別のファイルから印刷機能を取得し、それをロードして印刷機能を実行する必要があります。

次のコマンドを使用して、ghc バージョン 7.4.1 でコードをコンパイルします。

ghc -package ghc --make Api.hs

ただし、次のエラーが表示されます。

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

私は何を間違っていますか?私は GHC API のドキュメントを確認しましたが、この種のことのほとんどを理解するには十分に精通していません。

4

2 に答える 2

6

チュートリアルは古くなっています。ghc-7.0.* 以前では、 の型defaultErorHandler

defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => DynFlags -> m a -> m a

defaultDynFlags単なる値でした。

ghc-7.2.* の時点で、 の型defaultErrorHandler

defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => LogAction -> m a -> m a

defaultDynFlags関数です

defaultDynFlags :: Settings -> DynFlags

そしてLogAction同義語です

type LogAction = Severity -> SrcSpan -> PprStyle -> Message -> IO ()

7.6 では、これが再び変更されました。

defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => FatalMessager -> FlushOut -> m a -> m a

type FatalMessager = String -> IO ()

のラッパーFlushOutです。newtypeIO ()

私は 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 ()
于 2012-10-08T14:30:00.730 に答える
2

動的読み込みの完全な例を次に示します。これもここでホストされています。

DynLoad.hs

-----------------------------------------------------------------------------
-- | Example for loading Haskell source code dynamically using the GHC api
-- Useful links:
-- GHC api:
-- http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html
-- Wiki:
-- http://www.haskell.org/haskellwiki/GHC/As_a_library
-----------------------------------------------------------------------------
module DynLoad where

import GHC
import GhcMonad (liftIO)
import GHC.Paths (libdir)
import Name (getOccString)
import Data.Dynamic (fromDyn)

-- |  List all exports of this module
--    and evaluate a symbol from a module DynTest 
main = 
  runGhc (Just libdir) $ do
    putString ":::Display exports of modules:::"
    modSums <- initSession ["DynLoad","DynTest"]
    let thisModSum = head modSums
    exports <- listExports thisModSum
    mapM_ putString exports

    putString ":::Evaluate a name from module DynTest:::"
    importDecl_RdrName <- parseImportDecl "import DynTest as D"
    setContext [IIDecl importDecl_RdrName]
    dynVal <- dynCompileExpr "D.aString"
    liftIO $ print $ (fromDyn dynVal "nope-nothing")

-- | Init interactive session and load modules
initSession modStrNames = do
  dflags <- getSessionDynFlags
  setSessionDynFlags $ dflags {
    hscTarget = HscInterpreted
    , ghcLink   = LinkInMemory
    }
  targets <- mapM
              (\modStrName -> do
                  putString modStrName
                  target <- guessTarget ("*"++modStrName++".hs") Nothing
                  return target
              ) modStrNames
  setTargets targets
  load LoadAllTargets
  modSums <- mapM
              (\modStrName -> do
                  putString modStrName
                  modSum <- getModSummary $ mkModuleName modStrName
                  return $ ms_mod modSum
              ) modStrNames
  return modSums

-- | List exported names of this or a sibling module
listExports mod = do
  maybeModInfo <- getModuleInfo mod
  case maybeModInfo of
    (Just modInfo) -> do
      let expNames = modInfoExports modInfo
          expStrNames = map getOccString expNames
      return expStrNames
    _ -> return []

-- | Util for printing
putString = liftIO . putStrLn

ロードするファイルの例を次に示します。

DynTest.hs

module DynTest where


aString = "Hello"
于 2014-02-22T17:02:47.123 に答える