Opened 9 years ago

Closed 7 years ago

#2399 closed feature request (fixed)

Template Haskell: support for view patterns

Reported by: fons Owned by: igloo
Priority: low Milestone:
Component: Template Haskell Version: 6.11
Keywords: Cc: rwbarton@…, audreyt@…, duncan2nd@…, reiner.pope@…, id@…, vogt.adam@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

TH's Pat type doesn't include a constructor for view patterns, which would ceratinly be useful.

As an example, Reid Barton suggested using view patterns for creating a regular expression quasiquoter (rx) [1].

For example, to check if a string matches certain regular expresion:

example x = case x of
 [$rx|.*foo.*] -> "contains foo"
 _             -> "doesn't contain foo"

Using pattern views, the quasiquoter would expand to

example x = case x of
 ((=~".*foo.*")->True) -> "contains foo"
 _             -> "doesn't contain foo"

[1] http://www.haskell.org/pipermail/template-haskell/2008-June/thread.html#669

Attachments (3)

viewpatterns-ghc.dpatch (161.7 KB) - added by reinerp 7 years ago.
viewpatterns-th.dpatch (3.9 KB) - added by reinerp 7 years ago.
viewpatterns-test.dpatch (89.6 KB) - added by reinerp 7 years ago.

Download all attachments as: .zip

Change History (20)

comment:1 Changed 9 years ago by rwbarton

Cc: rwbarton@… added

comment:2 Changed 9 years ago by simonpj

difficulty: Unknown
Milestone: _|_
Priority: normallow

Yes, there are many ways in which Template Haskell lags the various GHC extensions, and view patterns are only one of them. Furthermore, view patterns are a rather new and experimental feature, so it seems premature to "bless" them in TH.

In any case, it's probably fairly easy to add a guard instead, since you are generating the program with a TH program.

Simon

comment:3 Changed 9 years ago by AudreyTang

Simon, it's difficult to add a guard there, because a QuasiQuoter accepts the pattern-generation function of the form:

quoteExprPat :: String -> TH.PatQ

But in TH, Guard is part of Body, so a quasiquoter designated to the PatQ side cannot affect the BodyQ side.

As there seems to be no other Pat constructors that's useful for a [$rx|...|] at the pattern side, would you consider accepting a patch that adds ViewP for 6.10?

Cheers,

Audrey

(The context for [$rx|...|] is http://hackage.haskell.org/cgi-bin/hackage-scripts/package/regexqq btw.)

comment:4 Changed 9 years ago by AudreyTang

Cc: audreyt@… added

comment:5 Changed 9 years ago by simonpj

Ah I see. I'd missed the quasiquoter connnection.

One way to fix this would be to add view patterns to TH. But it made me wonder: why aren't pattern guards compositional? At the moment they are resolutely top-level. And, as you say, not part of patterns. But syntax aside it would make perfect sense to make them part of a pattern:

  pat ::= var |  C pat1 ... patn
       |  pat|quals

where qual is a pattern-guard "qualifier". So (again, syntax aside) you could write

  f (x | x>3) = ...

  g ([y] | Just z <- lookup y) = ...

That would push pattern guards into the syntax of patterns. Now view patterns are syntactic sugar:

  (exp -> pat)   means   (x | pat <- exp x)
  where x is fresh

The reverse encoding is also possible

  (pat | quals)  means   (f -> Just (v1,...,vn))
where
  (v1,...,vn) are the variables bound by pat
  f pat | quals = Just vs

I'm not sure I'm advocating this (yet!), but I hadn't thought of it before so I thought I'd jot it down.

If TH users agree about just how to beef up patterns, I'm not against adding it. I'm just a bit conscious that view patterns are experimental and the more concrete we pour the harder it becomes to change.

Simon

comment:6 Changed 9 years ago by simonmar

Architecture: UnknownUnknown/Multiple

comment:7 Changed 9 years ago by simonmar

Operating System: UnknownUnknown/Multiple

comment:8 Changed 9 years ago by duncan2nd

Cc: duncan2nd@… added

comment:9 Changed 9 years ago by reinerp

Cc: reiner.pope@… added

comment:10 Changed 9 years ago by guest

Cc: id@… added

comment:11 Changed 9 years ago by porges

Version: 6.96.11

I came across this limitation also, while trying to write something to emulate Erlang's BitSyntax.

Erlang allows you to write:

<<H:2,T:6>> = <<"A">>

And then H and T are both bound to 1. Similarly:

<<01000001>> == <<"A">>

is true.

I was hoping to be able to write a quasiquoter to do something like this:

highBitSet
Word8 → Bool highBitSet [$bits| H:1, _:7 |] = H

But this currently is not possible (AFAIK!). So, basically I'd like to put a vote in for this.

Would this be a hard change to make?

comment:12 Changed 9 years ago by simonpj

What is the "change" that you advocate? The one that this ticket started with, namely adding view patterns to TH?

I have not looked into it in detail, but I don't think it's hard. As usual for TH, it means

  • Design the TH syntax data types
  • Write code in GHC to convert between TH and HsSyn

No rocket science. The trouble is that these TH extensions never get to the top of my priority list! But nagging is good... that ups the priority. I also always hope that someone else will to the work and send a patch!

Simon

comment:13 Changed 8 years ago by aavogt

Cc: vogt.adam@… added
Type of failure: None/Unknown

Improved Pat could address #3919

Changed 7 years ago by reinerp

Attachment: viewpatterns-ghc.dpatch added

Changed 7 years ago by reinerp

Attachment: viewpatterns-th.dpatch added

Changed 7 years ago by reinerp

Attachment: viewpatterns-test.dpatch added

comment:14 Changed 7 years ago by reinerp

Owner: set to igloo

I've attached patches (to ghc, template-haskell, and the testsuite) which implement and test the request. The Pat datatype in template-haskell now has a constructor ViewP Exp Pat, which is recognised when splicing. Also, GHC no longer complains about "exotic patterns" when writing things like [p|(id -> x)|].

My thought about view patterns versus Simon's "compositional pattern guards": view patterns are simpler. In particular, an important motivation seems to be for pattern quasiquoters. The main feature such quasiquoters require is being able to do computation before performing the pattern match, and the ViewP constructor expresses exactly that, and no more.

In my patch, I have left the ViewP case of Language.Haskell.TH.Lib.rename as a fail. To implement this case would seem to require extending rename to expressions as well as just patterns; and in any case, I am not sure of the purpose of this function.

comment:15 Changed 7 years ago by reinerp

Status: newpatch

comment:16 Changed 7 years ago by simonpj

Status: patchmerge

Thank you Reiner. I've applied the patches. I agree with your comment about rename; indeed I propose to nuke it altogether #4423.

Patches are:

-- GHC
Sun Oct 10 14:17:20 BST 2010  Reiner Pope <reiner.pope@gmail.com>
  * Template Haskell: add view patterns (Trac #2399)

-- template haskell library
Sun Oct 10 13:39:05 BST 2010  Reiner Pope <reiner.pope@gmail.com
  * Added view patterns (Trac #2399)

-- testsuite
Sun Oct 10 13:09:43 BST 2010  Reiner Pope <reiner.pope@gmail.com>
  * Add tests for view patterns in template haskell (Trac #2399)

I'd quite like to push this into 7.0 if we still have time. It's an API change so we can't do it in a patch release.

Simon

comment:17 Changed 7 years ago by igloo

Resolution: fixed
Status: mergeclosed

All 3 merged.

Note: See TracTickets for help on using tickets.