Haskell: Template Haskell and the scope

放肆的年华 提交于 2019-12-01 03:27:11

If you reorder your code as follows, it works:

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

data None = None { _f :: Int }

type Simpl = Env

type Env = Int

makeLenses ''None

When you use Template Haskell splices to add new top-level declarations to your code, as makeLenses does, the order of declarations in your code suddenly matters!

The reason is that normally compiling a Haskell program involves first collecting all the top-level declarations and reordering them internally to put them in dependency order, and then compiling them one by one (or group by group for mutually recursive declarations).

With new declarations being introduced by running arbitrary code, because GHC doesn't know which declarations makeLenses might need to run, and also it doesn't know which new declarations it will produce. So it can't put the whole file in dependency order and just sort of gives up and expects the user to do it themselves, at least for deciding whether declarations should go before or after the splice.

The only online reference I can find that explains this is in the original Template Haskell paper, section 7.2, where it says that the algorithm is:

  • Group the declarations as follows:
[d1,...,da]
splice ea
[da+2,...,db]
splice eb
...
splice ez
[dz+2,...,dN]

where the only splice declarations are the ones indicated explicitly, so that each group [d1,...,da], etc, are all ordinary Haskell declarations.

  • Perform conventional dependency analysis, followed by type checking, on the first group. All its free variables should be in scope.

So the problem here is that the first group of declarations before the splice is being handled separately to the second group after the splice, and it can't see the definition of Env.

My general rule of thumb is to put splices like this at the bottom of the file if possible, but I don't think it's guaranteed that this will always work.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!