[Haskell-cafe] Is Template Haskell a suitable macro language?

2007-04-24 Thread Joel Reymont
I'm finding myself dealing with several large abstract syntax trees  
that are very similar in nature. The constructor names would be the  
same or one type may be a small extension of another.


This is something that I wouldn't worry about with Lisp, for example,  
as I would create a bunch of macros for creating syntax trees and  
reuse them all over. I cannot do this in Haskell, though, as my  
macros are functions and so I must repeat them for every AST since  
they return different types.


I'm wondering if Template Haskell is a suitable replacement for Lisp  
macros.


What is the consensus?

Thanks, Joel

--
http://wagerlabs.com/





___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Is Template Haskell a suitable macro language?

2007-04-24 Thread Robin Green
On Tue, 24 Apr 2007 14:23:47 +0100
Joel Reymont [EMAIL PROTECTED] wrote:

 I'm finding myself dealing with several large abstract syntax trees  
 that are very similar in nature. The constructor names would be the  
 same or one type may be a small extension of another.
 
 This is something that I wouldn't worry about with Lisp, for
 example, as I would create a bunch of macros for creating syntax
 trees and reuse them all over. I cannot do this in Haskell, though,
 as my macros are functions and so I must repeat them for every AST
 since they return different types.
 
 I'm wondering if Template Haskell is a suitable replacement for Lisp  
 macros.
 
 What is the consensus?

I saw your earlier post on abstract syntax trees, and I have indeed
been using Template Haskell for processing syntax trees. (Sorry I
didn't reply earlier.) It works quite well, yes.

Here's my success story. Basically I have two modules, Abstract and
Concrete, which define data types for abstract and concrete syntax
respectively. The Abstract module also contains code to convert
concrete syntax (i.e. what comes out of the parser) into abstract
syntax, and the code that just does copying (i.e. the boilerplate code)
is generated by Template Haskell code.

What I do looks like this:


$(let
 preprocess :: [Dec] - Q [Dec]
 -- definition omitted

 in preprocess =
   [d|type Param = (Ident, Term)

  data FixBody = FixBody Ident [Param] (Maybe Annotation)
(Maybe Term) Term deriving (Typeable, Data, Eq)
  data MatchItem = MatchItem Term (Maybe Ident) (Maybe Term)
deriving (Typeable, Data, Eq)
  data IdentWithParams = IdentWithParams Ident [Param] (Maybe
Term) deriving (Typeable, Data, Eq)

  class Abstraction c a {- | c - a -} where { abstractL ::
Monad m = c - StateT [(Ident,Term)] m a }

#include common2.inc
   |])

Let me explain what's going on here, starting from the bottom. The
order of these parts is very important! The #include common2.inc
includes the type definitions which are common to both modules. (I
actually maintain a file common.inc and then that is preprocessed to
replace newlines with semicolons, in order to avoid the problem that
would otherwise occur that the file would be included at the wrong
identation level. Although the file is still included at the wrong
indentation level, apparently the use of semicolons mollifies ghc!) The
reason why I don't just put the stuff in common2.inc into another
module is because it refers to types that are defined *differently* in
each syntax! So I really am using cpp [actually, cpphs] for an
appropriate purpose here.

The class Abstraction defines a method abstractL. It is defined for
every concrete syntax data type and specifies how to translate that
type into abstract syntax (except the top-level which is handled
differently). The fundep is commented out because (a) ghc rejected it
and (b) I didn't need it anyway.

The preprocess function then takes all of the decls between [d| and |]
as input, passes through the declarations before the class declaration
(i.e. the ones that are not the same) without looking at them any
further, and then generates instances of the class for each data
declaration given below the class (i.e. all the types which are in
common, where only automatic copying code needs to be generated). It
also passes through all of the declarations given as input.

Why not simply put the initial declarations at the top of the file?
Well, ghc rejects that, if I remember correctly, because they refer to
other types which have yet to be generated (well, passed through) by
Template Haskell. Template Haskell seems to break the general principle
in Haskell that one can refer to a declaration in the same module,
textually before that declaration.

-- 
Robin
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Is Template Haskell a suitable macro language?

2007-04-24 Thread Jacques Carette

Magnus Jonsson wrote:
I have the same problem too when using Haskell. The more I try to 
enforce static guarantees the more I get lots of datatypes that are 
similar except for one or two constructors. The best way I have found 
to avoid this is to simply give up on some of the static guarantees 
and just use one datatype that contains all the constructors. Less 
static guarantees but also less needless type coaxing between 90% 
similar types. I haven't tried using macros.
In Ocaml, you can frequently use polymorphic variants to get the same 
effect.


Which means that if you are willing to do enough type-class-hackery, it 
should, in principle, be possible to do the same in Haskell.  But it 
sure isn't as convenient!


This all points to some clear need for more ``flavours'' of polymorphism 
being needed (in Haskell), to be able to express *in the type system* 
what TH allows you to say outside.


Jacques
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Is Template Haskell a suitable macro language?

2007-04-24 Thread Josef Svenningsson

On 4/24/07, Jacques Carette [EMAIL PROTECTED] wrote:

In Ocaml, you can frequently use polymorphic variants to get the same
effect.

Which means that if you are willing to do enough type-class-hackery, it
should, in principle, be possible to do the same in Haskell.  But it
sure isn't as convenient!


You seem to imply that there is an encoding of polymorphic variants in
Haskell using type classes. While I know that it's possible to achieve
similar effects using type classes I haven't seen a direct encoding.
If there is such an encoding I would be very interested to hear about
it.


This all points to some clear need for more ``flavours'' of polymorphism
being needed (in Haskell), to be able to express *in the type system*
what TH allows you to say outside.


I totally agree with this.

Cheers,

Josef
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Is Template Haskell a suitable macro language?

2007-04-24 Thread Jacques Carette

Josef Svenningsson wrote:

On 4/24/07, Jacques Carette [EMAIL PROTECTED] wrote:

In Ocaml, you can frequently use polymorphic variants to get the same
effect.

Which means that if you are willing to do enough type-class-hackery, it
should, in principle, be possible to do the same in Haskell.  But it
sure isn't as convenient!


You seem to imply that there is an encoding of polymorphic variants in
Haskell using type classes. While I know that it's possible to achieve
similar effects using type classes I haven't seen a direct encoding.
If there is such an encoding I would be very interested to hear about
it.

As usual, look for a solution from Oleg:
http://www.haskell.org/pipermail/haskell/2006-July/018172.html

There was also a proposal by Koji Kagawa (published at Haskell '06)
http://portal.acm.org/citation.cfm?id=1159842.1159848coll=dl=ACMtype=seriesidx=1159842part=ProceedingsWantType=Proceedingstitle=HaskellCFID=15151515CFTOKEN=6184618

Jacques
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe