On Jan 26, 2007, at 6:22 PM, Claus Reinke wrote:
2) There are other reasons why I want to use Haskell-98 and
would like to be able to use other compilers. Thus, I'd want a
pattern-binder preprocessor (extending GHC is not as important to
me).
I see. though I'd hope that as long as we keep our extensions
simple and
general enough, the other implementations will pick them up anyway.
Here's my motivating example. Here's a fragment for an STG
interpreter in Haskell-98:
{{{
rule_CASE_ELIM (Case p alts, s, h, o) =
do
ConApp c as <- ptsTo p h
let matchAlt (Alt c' vs e) | c == c' = Just (vs,e)
matchAlt _ = Nothing
(vs,e) <- matchFirst matchAlt alts
return (e `sub` (vs,as), s, h, o)
}}}
yes, abstract machines have inspired many a pattern match extension!-)
are we in Maybe, or in anything more complex?
Yep, just Maybe.
view patterns don't seem to apply, but pattern guards do, and
lambda-match helps with the local function pattern (ignoring the
Match type tag for the moment; given the revival of interest in
pattern functions, eg., in view patterns, I ought to try and see
whether I can get rid of the type tag in my library for the special
case of Maybe):
{{{
rule_CASE_ELIM =
(| (Case p alts, s, h, o) | ConApp c as <- ptsTo p h
, (vs,e) <- matchFirst (| (Alt c' vs e) | c == c' ->(vs,e) )
alts
-> (e `sub` (vs,as), s, h, o) )
}}}
which isn't quite as abstract as the pattern binder/combinator
version,
but at least I can see the scoping,
Thanks for showing how it looks with lambda-match, I see that lambda-
matches use
more than patterns, they use guards too.
which I am at a loss with in the pattern
binder version:
I'd like it to have a textual form just a little more abstract, I
can do that with pattern binders and some appropriate combinators:
{{{
rule_CASE_ELIM =
{ (Case p alts , s, h, o) }
&&& ptsTo p h === { ConApp c as }
&&& alts === matchFirst { Alt #c vs e }
.->
(e `sub` (vs,as), s, h, o)
}}}
I'll leave it as an exercise to figure out how the last is
parenthesized ;-).
ok, I give up. there seem to be some new combinators,
yes, but nothing fancy:
(&&&) :: (a -> Maybe b) -> (b -> Maybe c) -> a -> Maybe c
(&&&) = (.:) -- as in the paper
(===) :: a -> (a -> Maybe b) -> Maybe b
(===) a p = p a
and the pattern binder variables are no longer distinguishable (via
$).
In this example I'm dropping the $: it's less clear what's going on
but it looks cleaner,
more like Haskell patterns.
but unless you've changed the translation as well, the only way the
scopes are going to come out right is if the layout is a lie, right?
The layout /is/ a lie :-( but the scope rule is pretty simple: in
this expression
{p} `op` e
everything bound in p scopes over all e.
So, all the variables in the {p}'s above scope to the end of the RHS
expression.
and how does the translation apply to pattern binders not in an
infix application, in particular, how do vs/e get to
the rhs of .->?
Claus
All the pattern binders here /are/ in an infix application, here's
the parenthesized version:
{{{
rule_CASE_ELIM =
{ (Case p alts , s, h, o) }
&&& (ptsTo p h ==> { ConApp c as }
&&& (alts === (matchFirst ({ Alt #c vs e }
.->
(e `sub` (vs,as), s, h, o)))))
}}}
(Oops, I see I'm using # where in the paper I used "=".)
I also fixed a type error (nothing like ghci to fix some design
problems), I'm now using
an additional (rather simple) combinator:
(==>) :: Maybe a -> (a -> Maybe b) -> Maybe b
(==>) = (>>=)
- Mark
_______________________________________________
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime