GHC API - GHC 7.2 を使用してコンパイルされたモジュールから Haskell コードを動的にロードする方法は? 質問する

GHC API - GHC 7.2 を使用してコンパイルされたモジュールから Haskell コードを動的にロードする方法は? 質問する

GHC APIを使用してモジュールからコンパイルされたコードを動的にロードする既存のHaskell関数があります。これはブログ投稿のコードに基づいています。Haskell でのモジュールの動的コンパイルとロード

このコードは GHC 7.0 では正常に動作しますが、GHC API が変更されたため、GHC 7.2 でコンパイルするには若干の変更が必要でした。

このコードは、GHC 7.2 ではランタイム エラーをスローします。

mkTopLevEnv: not a home module (module name):(function name)

コードは

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 throws an error in GHC 7.2:
--
    (_,oi) <- GHC.getContext
    GHC.setContext [m] oi
--------------------------------------------------------

    fetched <- GHC.compileExpr (moduleName ++ "." ++ externalFuncName)
    return (Unsafe.Coerce.unsafeCoerce fetched :: [LispVal] -> IOThrowsError LispVal)
  defineVar env internalFuncName (IOFunc result)

参考までに、完全なコードはオンラインで入手可能です。FFI.hs (github.com)

この問題を修正または回避する方法を知っている人はいますか?

また、これは GHC 7.2 の新しい Safe Haskell の変更によって発生したものでしょうか、それとも GHC API の変更によるものでしょうか?

ベストアンサー1

現在のモジュールコンテキストは、現在コンパイル中のモジュール用に予約されています。つまり、コンテキストでモジュールを指定する場合、明示的にない外部にある。

代わりに、 の 2 番目の引数で、必要なモジュールをインポートとして指定する必要がありますsetContext。これは次のように実行できます。

GHC.setContext []
  -- import qualified Module
  [ (GHC.simpleImportDecl . GHC.mkModuleName $ moduleName)
    { GHC.ideclQualified = True
    }
  -- -- import qualified Data.Dynamic
  -- , (GHC.simpleImportDecl . GHC.mkModuleName $ "Data.Dynamic")
  --   { GHC.ideclQualified = True
  --   }
  ]
fetched <- GHC.compileExpr $ moduleName ++ "." ++ externalFuncName
return . unsafeCoerce $ fetched
-- or:
-- fetched <- GHC.dynCompileExpr $ moduleName ++ "." ++ externalFuncName
-- return . fromDynamic (error "Illegal type cast") $ fetched

追伸GHC.dynCompileExpr:代わりに を使うと、 を避けることができるので良いかもしれません。を動作させるには、 のunsafeCoerce修飾されたインポートをコンテキストに追加する必要がありますが、Data.DynamicData.Dynamic.Dynamic一般的に、型エラーをより適切に処理できるため、 value の方が扱いやすくなります。そのためのコードを上記のコードにコメントとして追加しました。


アップデート

GHC 7.4.1 の構文は次のとおりです。

GHC.setContext  
  -- import qualified Module
  [ GHC.IIDecl $ 
    (GHC.simpleImportDecl . GHC.mkModuleName $ moduleName)
    {GHC.ideclQualified = True}
  ]

おすすめ記事