Type synonyms “not in scope” when using Template Haskell

对着背影说爱祢 提交于 2019-12-23 10:49:31

问题


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

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