New Proposal: EasyMacros

Anton Felix Lorenzen anfelor at posteo.de
Wed May 18 19:10:53 UTC 2016


Hello list,

I want to propose a new way of writing template-haskell macros.
It is based on the idea, that syntax like this:
do {
    x <- getLine;
    putStrLn x;
}
should be parsed into:
$( do
    [ [| x <- getLine |]
    , [| putStrLn x   |]
    ] )
Then a function (do :: NonEmpty ExpQ -> ExpQ) will be called
and executed.

This would allow for a couple of useful macros:
   - do
   - case
   - fold -- fold the ExpQs into one, see below for details
   - eval -- evaluate ExpQs at compile-time
   - (maybe even) hamlet -- evaluate hamlet QQ
   - CPP replacements?

Nothing will be added which isn't possible today.
Nonetheless it will allow for a much cleaner syntax
and by this make things usable which weren't usable before.

Also it might be easier to implement new features.
For example ApplicativeDo and RecursiveDo
could have been implemented by a hackage package.
MultiWayIf could be a function, too.

apply
   [1..(10*365)]
   map (replicate 3)
   concat

conc
   "Hello World! \n"
   "How are you? \n"

Greetings,
Anton

===== Example Macros =====

see in context: https://github.com/anfelor/EasyMacros

conc = fold [| (++) |]
apply = fold [|flip ($)|]

fold :: ExpQ -- (a -> b -> c)
    -> NonEmpty (Q Exp) -> Q Exp
fold _ (a :| []) = a
fold fn (a :| b : xs) = fold fn (([| fn $a $b |]) :| xs)

do_ :: NonEmpty (Q Stmt) -> Q Exp
do_ (x :| []) = x >>= \case
      BindS _ _ -> fail "The last statement in a 'do' block must be an 
expression"
      NoBindS e -> return e
do_ (x :| xs) = x >>= \case
      BindS pat exp -> [| $(return exp) >>= \ $(return pat) -> $(do_ 
(fromList xs)) |]
      NoBindS   exp -> [| $(return exp) >> $(do_ (fromList xs)) |]


More information about the Haskell-prime mailing list