Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does cabal recompile a module which contains Template Haskell?

I understand that cabal will recompile a module if the interface of any of its dependencies has changed. It seems that this simple rule does not hold if the module contains Template Haskell. In that case, even just adding a trailing newline character to a file in the module's (transitive) dependencies will cause the cabal to recompile the file.

Minimal example:

file: Foo.hs

module Foo where
foo = "foo"

file: FooTH.hs

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

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

file: MCVE.cabal

name:                MCVE
version:             0.1.0.0
synopsis:            MCVE
license:             MIT
license-file:        LICENSE
author:              tarleb
maintainer:          [email protected]
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

Adding a newline to Foo.hs, e.g. by running echo "\n" >> Foo.hs, will cause recompilation of module FooTH. This ceases to happen if the TH line in FooTH is commented out.

What is the reason for this, and is there a way to avoid this unnecessary recompilation?

like image 563
tarleb Avatar asked Nov 03 '18 21:11

tarleb


1 Answers

There's a feature in Template Haskell called addDependentFile, which adds metadata to the .hi file indicating that the source file in question depends on another file as well. To my knowledge, Cabal will always ask GHC to try to build, though it may have more intelligent logic. Stack tries to bypass that process, and has logic to parse the addDependentFile information out.

like image 170
Michael Snoyman Avatar answered Oct 15 '22 04:10

Michael Snoyman