问题
I am getting a strange error about a data type being "not in scope" when using Template Haskell.
Here is my Main.hs file:
{-# 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"
When trying to compile it, I get the following error:
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
This error occurs whether I use deriveJSON
or makeLenses
.
If I move the type Foo = Bar
line down past the use of Template Haskell, the file compiles fine.
What's causing this error?
Here is a .cabal
file and stack.yaml
file to compile this:
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
This is using ghc-7.10.1.
回答1:
This is caused by declaration groups when using Template Haskell. Here is an excerpt from the GHC Manual:
Top-level declaration splices break up a source file into delcaration groups. A declaration group is the group of declarations created by a top-level declaration splice, plus those following it, down to but not including the next top-level declaration splice. The first declaration group in a module includes all top-level definitions down to but not including the first top-level declaration splice.
Each declaration group is mutually recursive only within the group. Declaration groups can refer to definitions within previous groups, but not later ones.
In my original code, two declaration groups are created:
-- 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
The first declaration group cannot see Bar
, which is causing this error.
回答2:
Move the data Bar = ...
declaration before the template Haskell and it'll work:
type Foo = Bar
data Baz = Baz
data Bar = Bar
$(deriveJSON defaultOptions ''Baz)
$(makeLenses ''Baz)
来源:https://stackoverflow.com/questions/31979147/type-synonyms-not-in-scope-when-using-template-haskell