cabal 何时重新编译包含模板 Haskell 的模块?

When does cabal recompile a module which contains Template Haskell?

我知道如果任何依赖项的接口发生变化,cabal 将重新编译一个模块。如果模块包含模板 Haskell,这个简单的规则似乎不成立。在这种情况下,即使只是在模块的(传递)依赖项中向文件添加尾随换行符也会导致 cabal 重新编译文件。

最小示例:

文件:Foo.hs

module Foo where
foo = "foo"

文件:FooTH.hs

{-# LANGUAGE TemplateHaskell #-}
module FooTH where
import Data.Bifunctor.TH
import Foo

data FooPair a b = FooPair a b
$(deriveBifunctor ''FooPair)

文件:MCVE.cabal

name:                MCVE
version:             0.1.0.0
synopsis:            MCVE
license:             MIT
license-file:        LICENSE
author:              tarleb
maintainer:          tarleb@example.com
build-type:          Simple
extra-source-files:  CHANGELOG.md
cabal-version:       >=1.10

library
  exposed-modules:     Foo
                     , FooTH
  build-depends:       base >=4.8 && <4.13
                     , bifunctors
  default-language:    Haskell2010

向 Foo.hs 添加换行符,例如通过 运行 echo "\n" >> Foo.hs,将导致模块 FooTH 的重新编译。如果 FooTH 中的 TH 行被注释掉,这种情况就不会发生。

这是什么原因,有没有办法避免这种不必要的重新编译?

模板 Haskell 中有一个名为 addDependentFile 的功能,它向 .hi 文件添加元数据,表明相关源文件也依赖于另一个文件。据我所知,Cabal 会总是 要求 GHC 尝试构建,尽管它可能有更智能的逻辑。 Stack 试图绕过该过程,并具有解析 addDependentFile 信息的逻辑。