Skip to content

Dhall.TH functions should call addDependentFile #2518

Closed
@gelisam

Description

@gelisam

As previously recommended by @sellout here, when dhall code is loaded via TemplateHaskell, it is important to call addDependentFile on the dhall file. Otherwise, changes to that dhall file will appear to be ignored!

The problem

Here is a small example demonstrating the problem.

$ cat ./Main.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Main where

import Dhall.Core
import Dhall.TH

config :: Expr () ()
config = $(staticDhallExpression "./example.dhall")

main :: IO ()
main = do
  print config

$ echo 42 > example.dhall
$ ghc ./Main.hs
$ ./Main
NaturalLit 42

So far so good. Let's try changing the configuration:

$ echo 43 > example.dhall
$ ghc ./Main.hs
$ ./Main
NaturalLit 42

Oh no, the configuration change was ignored!

The workaround

One unappealing workaround is to clear away the build artifacts in order to force ghc to rebuild:

$ rm ./Main.o
$ ghc ./Main.hs
$ ./Main
NaturalLit 43

Towards a solution

A better fix is to use addDependentFile to tell ghc that if example.dhall changes, it needs to recompile the TemplateHaskell code which reads that file:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Main where

import Dhall.Core
import Dhall.TH
import Language.Haskell.TH.Syntax

config :: Expr () ()
config = $(do
  addDependentFile "./example.dhall"
  staticDhallExpression "./example.dhall")

main :: IO ()
main = do
  print config

ghc now rebuilds when the dhall file changes.

$ echo 42 > example.dhall
$ ghc ./Main.hs
$ ./Main
NaturalLit 42

$ echo 43 > example.dhall
$ ghc ./Main.hs
$ ./Main
NaturalLit 43

Not quite there

Alas, the above does not work in all cases. dhall is a language which supports imports, and thus it is possible for example.dhall to in turn depend on another dhall file:

$ echo "./other.dhall" > example.dhall

Now our addDependentFile "./example.dhall" is insufficient; we should also have included addDependentFile "./other.dhall"!

$ echo 42 > other.dhall
$ ghc ./Main.hs
$ ./Main
42

$ echo 43 > other.dhall
$ ghc ./Main.hs
$ ./Main
42

Proposed solution

Rather than putting the onus on the user of Dhall.TH to maintain a list of the dependencies of their dhall files, it would make a lot more sense if it was the responsibility of the Dhall.TH functions to call addDependentFile on all the imports they encounter in the process of evaluating a dhall expression.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions