GHC声明模块仅在不应该作为引导模块时可用

时间:2016-11-16 00:42:26

标签: haskell ghc

我有这个依赖图(忽略对第三方模块的依赖):

Main:
    GSI.Util
    GSI.Value
    GSI.Result
    GSI.Eval
    GSI.ByteCode
    GSI.Thread
GSI.Main:
    GSI.Value
    GSI.ByteCode
GSI.Thread:
    GSI.Util
    GSI.RTS
    GSI.Value
    GSI.Result
    GSI.Eval
GSI.Eval:
    GSI.Util
    GSI.RTS
    GSI.Value
    GSI.Result
    ACE
GSI.Eval (.hs-boot):
    GSI.Value
ACE:
    GSI.RTS
    GSI.Value
    GSI.ByteCode
    GSI.Result
    {-# SOURCE #-} GSI.Eval
GSI.ByteCode:
    GSI.Util
    GSI.Value
    {-# SOURCE #-} GSI.Thread
GSI.ByteCode (.hs-boot):
    {-# SOURCE #-} GSI.Value
    {-# SOURCE #-} GSI.Thread
GSI.Result:
    GSI.Util
    GSI.RTS
    GSI.Value
GSI.Value:
    GSI.Util
    GSI.RTS
    {-# SOURCE #-} GSI.ByteCode

(我希望进一步削减该图表,但老实说我很遗憾哪些部分是相关的。未列出的.hs-boot文件与我的代码没有依赖关系)。当我做的时候

ghc --make Main.hs

我收到此消息:

[10 of 13] Compiling ACE              ( ACE.hs, ACE.o ) [GSI.ByteCode changed]
module GSI.Thread cannot be linked; it is only available as a boot module

究竟是什么?我没有从Main导入GSI.Thread作为启动模块,那么GHC如何声称它只能作为启动模块使用? (而且,就此而言,为什么GHC只能检测到这种情况并自动包含非启动模块?)

1 个答案:

答案 0 :(得分:1)

实际问题是ACE和GSI.Value有一个循环依赖:

ACE -> GSI.Value -> GSI.Thread -> GSI.Eval -> ACE

这是一个无法解决的问题,因为ACE在Template Haskell接头中使用GSI.Value中的函数。这要求GHC动态加载GSI.Value以编译ACE;但这显然是不可能的。

解决方案是将Thread类型从GSI.Thread中移出,并转移到一个单独的模块,该模块可以避免对GSI.Eval或GSI.Value的任何依赖。