Retrieving annotations from the same module

2019-08-09 07:46发布

问题:

Suppose I define my own annotation type:

{-# LANGUAGE DeriveDataTypeable #-}
module Def where

import Data.Data

data MyAnn = MyAnn Int deriving (Show, Typeable, Data)

and some Template Haskell function to access it:

module TH where

import Def
import Language.Haskell.TH.Syntax

myAnn :: Name -> Q Exp
myAnn name = do
    [MyAnn x] <- reifyAnnotations (AnnLookupName name)
    lift x

I would now like to use it like this:

{-# LANGUAGE TemplateHaskell #-}
module Client where

import Def
import TH

x :: ()
x = ()
{-# ANN x (MyAnn 42) #-}

y :: Int
y = $(myAnn 'x)

But this fails because the myAnn invocation in the definition of y gets an empty list from reifyAnnotations.

It works if I split Client like this:

module Client1 where

import Def

x :: ()
x = ()
{-# ANN x (MyAnn 42) #-}

{-# LANGUAGE TemplateHaskell #-}
module Client2 where

import Client1
import TH

y :: Int
y = $(myAnn 'x)

Is there a way to get something like the monolithic Client module to work?

回答1:

This seems to be expected behavior according to the docs:

Accordingly, the type environment seen by reify includes all the top-level declarations up to the end of the immediately preceding declaration group, but no more.

An effective workaround for your problem is to force the start of a separate declaration group by including an empty top-level declaration splice, i.e. just

$(return [])