Personal tools

User:Zzo38/Proposal for macros

From HaskellWiki

Jump to: navigation, search

This document list proposal for use of macros in Haskell.

1 Defining macros

By convention the macros will start with underscore followed by an uppercase letter, but would not be enforced. Macro names can start with any lowercase letter.

This document reuses the type keyword to define macros (if the name is not capitalized, it is a macro), but the implementation could be different.

Macro parameters would be a token or a token block (such as in parentheses). Names would be normally hygienic.

Partially applied macros (like partially applied type synonyms) are not allowed except with other macros.

A macro might expand to an entire block of definitions, possibly with private names and include files, or to a single expression, or a type, or kind, etc.

Possibly a macro expansion could even include Template Haskell codes, which themself could even expand to macros.

Macros do not have to be referentially transparent, unlike functions. They could even count how many times it is used, to make a new unique name each time, like Template Haskell codes can also do.

2 Macros for catching pattern failure

Example:

{-# LANGUAGE Macro #-}
import Control.Exception.Macro;
a :: Int -> Int -> Int;
a 0 x = x;
a 1 x = x + x;
b :: Int -> Int -> Either String Int;
b = _Catch 2 a;
c :: Int -> Int -> IO Int;
c = _CatchIO 2 a;
d :: Int -> IO (Int -> Int);
d = _CatchIO 1 a;
e :: [String];
e = ["hello", "world", undefined];
f :: IO [String];
f = _CatchStrictIO 0 e do {
  case _This of {
    [] <- _Stop;
    h : t <- do {
      h;
      _Again t;
    };
  };
};

Meanings:

b 0 = Right;
b 2 = const $ Left "pattern match error";
c 0 = return;
c 2 = const $ fail "pattern match error";
d 0 = return id;
f = fail "undefined";

Note that _Catch and so on are macros, not functions. A macro is not a first-class value in the program, and cannot be used at run-time, but can have operations that a function doesn't have.

When calling the new function created by the macro, errors are converted to the return value instead (a function could not read undefined values, but a macro could change it into a different function so that it is not undefined).

You could specify strictifying with do-notation to ensure everything in there is defined before returning a value, so that an undefined value will be caught ahead of time.

User errors and pattern match errors can be caught even in a pure code, but out of memory error can only be caught in I/O actions.

3 Macros for values with multiple types

Example:

f x y = (either x x (y :: Either Int String)) :: Bool;

What would be type of f? There is no type, because x must be something with two types, such as a class method.

But you can make a macro:

type f x y = either x x y;

Which is allowed, it has no type. But you cannot partially apply it, since it is not a function.