Difference between revisions of "Toolmaking libraries"

From HaskellWiki
Jump to: navigation, search
 
Line 45: Line 45:
 
readSource :: String -> Module
 
readSource :: String -> Module
   
  +
{- queries on Module -}
 
funcs :: Module -> [FuncDec]
 
funcs :: Module -> [FuncDec]
 
types :: Module -> [TypeDec]
 
types :: Module -> [TypeDec]
Line 50: Line 51:
 
instances :: Module -> [InstanceDec]
 
instances :: Module -> [InstanceDec]
   
  +
{- compatibility - extended/custom version of lib will want additional such queries -}
  +
class MaybeH98 dec where
  +
isH98 :: dec -> Bool
  +
  +
-- instances of MaybeH98 for all Dec structures
  +
  +
{- queries on InstanceDec -}
  +
-- print out the 'head' of the instance, "instance <class> <parms>"
  +
showInstanceHead :: InstanceDec -> String
  +
showInstance :: InstanceDec -> String
  +
  +
{- queries on FuncDec -}
 
-- clearly I have done some handwaving, as FuncDecs'd need tying to their source for this
 
-- clearly I have done some handwaving, as FuncDecs'd need tying to their source for this
 
inferType :: FuncDec -> Type
 
inferType :: FuncDec -> Type

Revision as of 18:36, 24 March 2007

Basic concept

Writing tools involves duplicating work that gets done over and over, and which is affected by the existence of extensions. So let's define interfaces for libraries that make this easier and build some initial implementations, while letting new Haskell implementations with new extensions provide their own implementations that hopefully make the extensions less painful to deal with.

Views

Different tools need different information about code - for example, haddock doesn't care about terms at all, whereas other tools might want to know about dependencies and yet others might perform abstract interpretations on code. So we should provide different views of a source file, with different modules implementing them.

  1. Apps like Haddock need to see the bindings present in a module and some information about those bindings, but no terms. Some term-relevant analyses could still be usefully provided - so long as they're done on-demand, apps that don't need them won't be restricted by tighter well-formedness constraints.
  2. Other applications could use a desugared 'core' language (and preferably means to find the corresponding source for a given piece of core code). At least two variants would make sense:
    • An untyped core. Producing such a language isn't too hard, though there are arguments to be had as to how to handle type classes.
    • An explicitly typed core. This could be trickier - the Right Thing would appear to be a core sufficiently expressive to handle type-preserving translations from the numerous extensions kicking around. Type classes are again an issue, in that much of the work involved with them is in resolving which instance to use - this can be dealt with, but requires some thought.

Proposed interfaces

A proposal for a "just the names" interface (... where I've not filled in concrete details yet, feel free to add in the obvious):

-- [Item] corresponds to the order the items appear in the source
data Module = Module Identifier [Export] [Item]
data Export = ...
data Item = Comment String |
            Function FuncDec |
            Fixity FixityDec |
            Type TypeDec |
            Class ClassDec |
            Instance InstanceDec |
            ...

data FuncDec = FuncDec Identifier (Maybe Type)
data FixityDec = FixDec Fixity Int 
data Fixity = FLeft | FRight | FNon
data TypeDec = TypeDec {name :: Identifier,
                        parms,
                        constructors :: [DataConDec],
                        ...} |
               TypeSynonym ... |
               NewType ...
data ClassDec = ...
data InstanceDec = ...

data Type = ...

-- parse source
readSource :: String -> Module

{- queries on Module -}
funcs :: Module -> [FuncDec]
types :: Module -> [TypeDec]
classes :: Module -> [ClassDec]
instances :: Module -> [InstanceDec]

{- compatibility - extended/custom version of lib will want additional such queries -}
class MaybeH98 dec where
  isH98 :: dec -> Bool

-- instances of MaybeH98 for all Dec structures

{- queries on InstanceDec -}
-- print out the 'head' of the instance, "instance <class> <parms>"
showInstanceHead :: InstanceDec -> String
showInstance :: InstanceDec -> String

{- queries on FuncDec -}
-- clearly I have done some handwaving, as FuncDecs'd need tying to their source for this
inferType :: FuncDec -> Type

-- Any other useful queries want adding?