GHC 声称模块仅在不应作为引导模块时可用
GHC claims module only available as a boot module when it shouldn't be
我有这个依赖图(忽略对第三方模块的依赖):
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 不能检测到这种情况并自动包含非引导模块?)
实际问题是 ACE 和 GSI.Value 存在循环依赖关系:
ACE -> GSI.Value -> GSI.Thread -> GSI.Eval -> ACE
这是一个无法解决的问题,因为 ACE 在模板 Haskell 拼接中使用了来自 GSI.Value 的函数。这需要 GHC 动态加载 GSI.Value 才能编译 ACE;但这显然是不可能的。
解决方案是将 Thread 类型从 GSI.Thread 中移出,并移动到一个单独的模块中,以避免对 GSI.Eval 或 GSI.Value 的任何依赖。
我有这个依赖图(忽略对第三方模块的依赖):
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 不能检测到这种情况并自动包含非引导模块?)
实际问题是 ACE 和 GSI.Value 存在循环依赖关系:
ACE -> GSI.Value -> GSI.Thread -> GSI.Eval -> ACE
这是一个无法解决的问题,因为 ACE 在模板 Haskell 拼接中使用了来自 GSI.Value 的函数。这需要 GHC 动态加载 GSI.Value 才能编译 ACE;但这显然是不可能的。
解决方案是将 Thread 类型从 GSI.Thread 中移出,并移动到一个单独的模块中,以避免对 GSI.Eval 或 GSI.Value 的任何依赖。