输入同义词"不在范围"何时使用Template Haskell

时间:2015-08-13 03:43:08

标签: haskell ghc template-haskell type-synonyms

我收到一个奇怪的错误,关于数据类型是"不在范围"使用Template Haskell时。

这是我的Main.hs文件:

{-# LANGUAGE TemplateHaskell #-}

module Main where

import Control.Lens
import Data.Aeson
import Data.Aeson.TH

type Foo = Bar

data Baz = Baz
$(deriveJSON defaultOptions ''Baz)
-- $(makeLenses ''Baz)

data Bar = Bar

main :: IO ()
main = print "hello"

尝试编译时,我收到以下错误:

test-0.1.0.0: configure
Configuring test-0.1.0.0...
test-0.1.0.0: build
Building test-0.1.0.0...
Preprocessing executable 'test' for test-0.1.0.0...
[1 of 1] Compiling Main             ( Main.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.2.0/build/test/test-tmp/Main.o )

Main.hs:9:12:
    Not in scope: type constructor or class ‘Bar’

--  While building package test-0.1.0.0 using:
      /usr/bin/runhaskell -package=Cabal-1.22.2.0 -clear-package-db -global-package-db -package-db=/home/illabout/.stack/snapshots/x86_64-linux/nightly-2015-06-17/7.10.1/pkgdb/ /tmp/stack1699/Setup.hs --builddir=.stack-work/dist/x86_64-linux/Cabal-1.22.2.0/ build
    Process exited with code: ExitFailure 1

无论是使用deriveJSON还是makeLenses,都会出现此错误。

如果我将type Foo = Bar行移到模板Haskell的使用之后,则文件编译正常。

造成此错误的原因是什么?

这是一个.cabal文件和stack.yaml文件来编译它:

test.cabal:

name:                test
version:             0.1.0.0
build-type:          Simple
cabal-version:       >=1.10

executable test
  main-is:             Main.hs
  build-depends:       base >=4.8 && <4.9
                     , aeson >= 0.8 && < 0.9
                     , lens >= 4 && < 5
  default-language:    Haskell2010

stack.yaml:

flags: {}
packages:
- '.'
extra-deps: []
resolver: nightly-2015-06-17

这是使用ghc-7.10.1。

2 个答案:

答案 0 :(得分:8)

这是由使用Template Haskell时的声明组引起的。以下是GHC Manual

的摘录
  

顶级声明拼接将源文件分解为逐行扫描   组。声明组是由a创建的声明组   顶级声明拼接,以及跟随它的那些拼接,但不是   包括下一个顶级声明拼接。第一个宣言   模块中的组包括所有顶级定义,但不包括   包括第一个顶级声明拼接。

     

每个声明组仅在组内相互递归。   声明组可以参考以前组中的定义,   但不是后来 s。

在我的原始代码中,创建了两个声明组:

-- This is the start of the first declaration group.

type Foo = Bar

data Baz = Baz
$(deriveJSON defaultOptions ''Baz)

-- This is the start of the second declaration group.

data Bar = Bar

第一个声明组看不到导致此错误的Bar

答案 1 :(得分:4)

在模板Haskell之前移动data Bar = ...声明,它将起作用:

type Foo = Bar

data Baz = Baz
data Bar = Bar

$(deriveJSON defaultOptions ''Baz)
$(makeLenses ''Baz)