Annotation system for Haskell

Bulat Ziganshin bulat.ziganshin at gmail.com
Sun Nov 12 18:28:09 EST 2006


Both Java and C# provides annotations that can be used to pass some
additional information about code to around-language tools and queried
at program runtime via Reflection API:

[AuthorAttribute ("Ben Albahari")]
class A
{
    [Localizable(true)]
    public String Text {
        get {return text;
        }
        ...
    }
}


in the last poll for Haskell', it was widely noted that some form of
attribute (annotation) system for Haskell will be great, although
there is no any design yet. i think that i've found rather good one:

1. Attributes must be available at run-time via some library that
uses RTS-provided information, at compile-time for
TemplateHaskell-like language extensions using appropriate APIs, and
for 3rd-party tools like DrIFT using database generated by compiler
during compilation process

2. Attributes are linked to _entities_, which includes packages,
modules, values, types, classes and instances. Entity can be found by
specifying its _path_, say "package Foo -> module M -> class Eq ->
value (==)". Of course this path on practice may be written just as
"Foo:M:Eq:(==)". Because almost any module imports class Eq from
Prelude, we can find the very same entity by a number of various paths,
including "Base:Data.List:Eq:(==)" and "stm:Control.Concurrent.STM:Eq:(==)".
If module A imports module B qualified, then path may look as "Foo:A:B.f".
Of course, we will also need some way to get "current" package/module
name

3. It should be also possible to _enumerate_ all sub-entities of given entity
or all attributes of entity. I think that we should provide both ability to
enumerate all entities _available_ inside module and to
enumerate all entities _defined_ in the module

4. Each entity has a list of named attributes. We should provide a way
to define new attribute name together with its "sort". Using Haskell
type to define this "sort" looks like a natural solution:

[Declare Author :: String]
[Declare Deriving :: [String]]

[Author "Bulat"]
data T = X | Y
[^Deriving ["Eq","Ord"]]

5. Then, using a path to entity and attribute's name, one can easily get
attribute value: getAttr "Foo:M:T" "Author". Simplest solution is
just to return String representation of attribute value, leaving to
programmer the job of using "read" to convert this String value into
right type

I don't consider this in deeper details, but some form of dynamic
typing (Typeable/Data class) can also be used. Ideal solution will be
to allow programmer to define his own datatypes of attributes which
then may be used _both_ instead of [Declare] statements above and as
result type for getAttr function, say:

data MyAttrs = Author String
             | Deriving [String]
     deriving (Attribute)

[Author "Bulat"]
data T = X | Y
[^Deriving ["Eq","Ord"]]

use_reflection_api = case getAttr (CurrentPackage ++ ":" ++
                                   CurrentModule  ++ ":T")
                                 "Author"
                     of Author str -> str


In this scenario, standard (predefined) attributes may be just
imported as part of Prelude, and user-defined attributes may be
defined in current or imported module

But while this way greatly simplifies and makes almost type-safe the
most common case - using of well-known attributes, it should also be
possible to keep 2 features:
1) ability to declare new attribute types inside a module and use
these new attributes immediately inside the same module
2) ability to enumerate and get values of attributes of unknown types.
imagine, for example, attribute browsing tool


6. Returning to compiler/3rd-party tools interaction, we can now say
that attributes database for each module should be build during
compilation of this module. It is something very like .hi file, one per each
module compiled, but for external consumption. It looks natural to use
XML format here, so the entity path will be translated into the path of
appropriate xml file and xml path inside the file. Information in this file
don't limited to the attributes provided by module writers, it can
also contains any information compiler may provide (types of values,
code metrics, options used when compiling module) and 3rd-party tools
can also add their own information here

it seems that also some indexing/xml merging tools should arise at
some moment to speed up access to this database, especially to databases
of installed packages

  

-- 
Best regards,
 Bulat                          mailto:Bulat.Ziganshin at gmail.com



More information about the Haskell-prime mailing list