[Haskell-cafe] combinators for a simple grammar

Stefan O'Rear stefanor at cox.net
Mon Aug 6 22:49:30 EDT 2007


On Mon, Aug 06, 2007 at 10:33:01PM -0400, Rahul Kapoor wrote:
> I am having problems coming up with nice combinators for a simple
> DSEL. The abstract syntax is simply given by the types:
> 
> data SearchCondition = SearchCondition BoolTerm | OpOr SearchCondition  BoolTerm
> 
> data BoolTerm = BoolTerm BoolFactor | OpAnd BoolTerm BoolFactor
> 
> data BoolFactor = Constant Bool
> 
> 
> My current combinators are
> 
> (.||.) :: SearchCondition -> BoolTerm -> SearchCondition
> (.||.) sc term = OpOr sc term
> 
> (.&&.) :: BoolTerm -> BoolFactor -> BoolTerm
> (.&&.) term fact = OpAnd term fact
> 
> which allow you to write expression of the form
> 
> factTrue = Constant True
> termTrue = BoolTerm factTrue
> scTrue = SearchCondition termTrue
> 
> sc = scTrue .||. termTrue .||. termTrue .&&. factTrue
> 
> I am wondering it it is possible to define combinators to hide the
> structure of the grammar from the user to some extent, so that the
> user can simply write things like
> 
> sc = True .||.True .||. True .&&. False
> 
> or
> 
> sc = const True .||. const True .||. const True .&&. const  False
> 
> That is the user does not have to worry about the distinction between
> terms and factors (which exists solely for precedence in this case).
> 
> Or is it a better idea to just remove the precedence rules from the
> types and move it the part of the code that evaluates the expressions?

I think it would be better still to remove it from both and rely on
Haskell's built-in precedence parser.

data SearchCondition = Constant Bool
                     | SearchCondition :||: SearchCondition
                     | SearchCondition :&&: SearchCondition

infixr 3 :&&:
infixr 2 :||:

true = Constant True
false = Constant False

sc = true :||: true :||: true :&&: false

eval (Constant k) = k
eval (l :||: r) = eval l || eval r
eval (l :&&: r) = eval l && eval r

You can still hide the constructors if you want, of course.

Another idea is to directly represent search conditions as functions:

type SearchCondition = Object -> Bool
-- could be just Bool to match your example, but I imagine you were
-- simplifying, and making the leap from Bool to Object -> Bool is
-- not always obvious

(.||.) sc1 sc2 x = sc1 x || sc2 x
(.&&.) sc1 sc2 x = sc1 x && sc2 x
true x = True
false x = False

infixr 3 .&&.
infixl 2 .||.

-- eval is not needed!  You can just apply a search condition to an
-- object.  The downside of this is that applying is *all* you can do,
-- you can't optimize or analyze like you can with the explicit
-- approach.

Stefan
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070806/43a8908e/attachment.bin


More information about the Haskell-Cafe mailing list