Difference between revisions of "Toolmaking libraries"

From HaskellWiki
Jump to navigation Jump to search
Line 14: Line 14:
 
=== Proposed interfaces ===
 
=== 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):
+
A sketch proposal for a "just the names" interface (... where I've not filled in concrete details yet, feel free to add in the obvious):
   
 
<haskell>
 
<haskell>
Line 37: Line 37:
 
TypeSynonym ... |
 
TypeSynonym ... |
 
NewType ...
 
NewType ...
data ClassDec = ...
+
data ClassDec = ... -- keep abstract
data InstanceDec = ...
+
data InstanceDec = ... -- keep abstract
   
data Type = ...
+
data Type = ... -- keep abstract
   
 
-- parse source
 
-- parse source
Line 60: Line 60:
 
-- print out the 'head' of the instance, "instance <class> <parms>"
 
-- print out the 'head' of the instance, "instance <class> <parms>"
 
showInstanceHead :: InstanceDec -> String
 
showInstanceHead :: InstanceDec -> String
showInstance :: InstanceDec -> String
+
showInstance :: InstanceDec -> String -- use for Show instance
   
 
{- queries on FuncDec -}
 
{- 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
  +
  +
{- queries on Type -}
  +
showType :: Type -> String -- use for Show instance, should be legit Haskell code
   
 
-- Any other useful queries want adding?
 
-- Any other useful queries want adding?

Revision as of 18:39, 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 sketch 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 = ... -- keep abstract
data InstanceDec = ... -- keep abstract

data Type = ... -- keep abstract

-- 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 -- use for Show instance

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

{- queries on Type -}
showType :: Type -> String -- use for Show instance, should be legit Haskell code

-- Any other useful queries want adding?