This package is a small compiler plugin that transitively propagates, and reifies, annotations. To get started, try attaching some annotations to some values:
{-# OPTIONS_GHC -fplugin=TransitiveAnns.Plugin #-}
import TransitiveAnns.Types
{-# ANN test3 (Annotation Remote "hello from" "test3") #-}
test3 :: Int
test3 = 4
{-# ANN test2 (Annotation Remote "hello from" "test2") #-}
test2 :: Int
test2 = test3and then we can reify them:
test :: ([Annotation], Int)
test = withAnnotations test2with result:
( [ Annotation Remote "hello from" "test3"
, Annotation Remote "hello from" "test2"
]
, 4
)Better yet, it works across module boundaries!
Internally, this plugin consists of two parts: a CoreToDo plugin, and a
typechecker plugin. The CoreToDo runs after the module has been compiled, looks
up every function with an Annotation, and then also attaches it to any
function which calls an annotated function. These get stuck in the ModIface,
so they are cached in the compiled artifacts.
The other half of the plugin is a solver for the following class:
class KnownAnnotations where
annotationsVal :: [Annotation]which returns every annotation attached to the function calling
annotationsVal. Of course, this dispatch plays nicely with the usual
constraint system, so you can delay its evaluation by adding a
KnownAnnotations => given constraint to your type signature.