I am reasonably convinced by the need for an extensible attribute-style specification such as Marcin has been proposing. However I am also intrigued by Alastair's "interesting" interpretation of one of my earlier suggestions, and it led me to the following proposal, modifying Marcin's design for default decls only slightly: Change foreign_decl ::= 'foreign' what foreign_name attributes varid '::' prim_type | 'foreign' 'default' attributes to foreign_decl ::= 'foreign' what [conid] [attributes] [foreign_name] varid '::' prim_type | 'foreign' 'library' conid attributes I also prefer to change attribute ::= varid | varid string_literal to attribute ::= varid | varid=string_literal The 'default' decl changes to a 'library' decl, and we now introduce a *name* for the set of default features. The conid is an arbitrary name chosen by the user; the library declaration *binds* that name to the given list of features. You can have as many library decls as you like - think of them simply as named collections of features. These names can then be used in a foreign import/export as an abbreviation for those feature specifiers. Additional attributes can be added within the foreign import decl to override ones from the named set, as in Marcin's proposal. So, for example, imagine I wanted to use both Gtk and bzip2 within a single Haskell module. First, set up a bunch of defaults for Gtk: foreign library Gtk header="<gtk/gtk.h>" header="<gtk/glib.h>" dll="libGTK.dll" stdcall unsafe (noting that the order of header files is important), and then another bunch of defaults for bzip2: foreign library Bzip2 header="bzip2.h" ccall When it comes to defining the imported functions, I just use the names I introduced earlier to access the defaults: foreign import Gtk "gtk_text_widget" textWidget :: String -> GtkWidget foreign import Bzip2 bzcat :: String -> Ptr () or, if I want to (say) add an extra header file and override an option for one particular import, I can easily do that: foreign import Gtk safe header="<extra_header.h>" "gtk_example" example :: String -> GtkWidget By the way, this implies that certain single-word features must be invertible - 'unsafe' can be overridden by 'safe', 'nonblocking' can be overridden by 'blocking', or whatever. I think this addresses Alastair's concerns about what happens to defaults when you cut+paste code from one place to another. With this proposal, if you forget to copy the library decl, the compiler will tell you that it doesn't know what defaults you intended, and can even tell you (for instance) "A 'foreign library Bzip2' decl is missing.". The name for a set of default decls is a conid rather than a varid, just to distinguish between the name of the feature *set* and the feature names themselves. They can appear in exactly the same position, and would otherwise have the same form in some cases. Marcin has already listed attributes we already know about, and here is my proposed initial list which coincides to some degree: . safe/unsafe (could rename to memsafe/memunsafe maybe?) . blocking/nonblocking . calling convention (stdcall,ccall,java,...) . header="..." (or maybe call it: include="...") . dll="..." (for interpreters under Windows) . unixso="..." (for interpreters under Unix) Note that 'dynamic' is *not* included in the possible attributes - I think that belongs properly to the function, not to the library. Marcin expressed a similar opinion I think. There is also a suggestion here to try to avoid conditional compilation: that we should have *different* attribute specs for the library name that would be required on different types of machine. Hence the naming of 'dll' and 'unixso' - and maybe there are more possibilities. Of course, this is not a panacea, as we know already from the 'gtk-config --libs' story, but it might go some way to helping. A compiler/interpreter would be free to ignore these specs for shared libraries if it thought it could do a better job by some other means. Regards, Malcolm