Opened 3 years ago

Last modified 3 months ago

#9671 new feature request

Allow expressions in patterns

Reported by: Iceland_jack Owned by:
Priority: normal Milestone:
Component: Compiler Version:
Keywords: PatternSynonyms Cc: cactus, RyanGlScott, dfeuer
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

I've outlined a proposal for extending pattern synonyms to depend on terms (PatternFamilies), the name is less than ideal but I'll keep the page under that name for now. The proposal's introduction has been rewritten.

The simplest use case are patterns that matches only when a set contains an element (IsMember) or when a set does not contain an element (NotMember):

    hasKeys :: Set Item -> IO ()
    hasKeys (IsMember  "keys") =             leaveHouse
    hasKeys (NotMember "keys") = findKeys >> leaveHouse

or a pattern that matches a map if the key exists:

used like this:

    age :: Map Person Age -> String
    age (Lookup "Alice" 60)  = "Alice is 60 years old!"
    age (Lookup "Alice" age) = "Alice is " ++ show age ++ "."
    age (Lookup "Bob" _)     = "No info on Alice but we know how old Bob is."
    age _                    = "..."

Further details and examples can be found here: PatternFamilies, I discussed it with several people ICFP 2014. This would not require a new extension but would extend PatternSynonyms. This feature can be quite useful, especially when working with deeply nested structures (ASTs, JSON, XML, ...).

If people are fine with it I will implement it.

Change History (12)

comment:1 Changed 3 years ago by simonpj

Your examples all use constants, but I assume you are going to allow this:

f :: Person -> Map Person Age -> Age
f p (Lookup p a) = a
f p _            = error ("No info on " ++ show p)

Now this is jolly confusing. In the pattern (Lookup p a), p is a bound occurence while a is a binding occurrence.

This distinction is made syntactically by view patterns:

f :: Person -> Map Person Age -> Age
f p ((\m -> lookup m p) -> a) = a

Here the stuff on the left of the view-pattern arrow -> are bound occurrences, while the stuff on the right is binding.

You could even have

f p (Lookup p p) = p

meaning

f p1 (Lookup p1 p2) = p2

To me, the lack of syntactic cues for what is bound and what is binding seems quite serious.

comment:2 Changed 3 years ago by cactus

Cc: cactus added

comment:3 Changed 3 years ago by cactus

The implementation is a straightforward desugaring into pattern synonyms and view patterns

That's how I started the work on pattern synonyms in the first place... spoiler alert: it never is :)

comment:4 Changed 3 years ago by cactus

+1 to SPJ on distinguishing pat and expr arguments. In fact, I think they should be distinguished even when introducing them as formal arguments.

comment:5 Changed 3 years ago by cactus

Keywords: PatternSynonyms added; patterns pattern synonyms removed

comment:6 Changed 3 years ago by thoughtpolice

Milestone: 7.10.17.12.1

Moving to 7.12.1 milestone; if you feel this is an error and should be addressed sooner, please move it back to the 7.10.1 milestone.

comment:7 Changed 22 months ago by thoughtpolice

Milestone: 7.12.18.0.1

Milestone renamed

comment:8 Changed 17 months ago by thomie

Milestone: 8.0.1

comment:9 Changed 9 months ago by RyanGlScott

Cc: RyanGlScott added

comment:10 Changed 3 months ago by dfeuer

Cc: dfeuer added

Is there a GHC proposal for this? I think it'd be pretty cool to get something similar, perhaps with an explicit separator between the arguments and the subpatterns.

comment:11 Changed 3 months ago by Iceland_jack

Is this a matter of finding good syntax or is it something fundamental? I'll get the ball rolling, help me pick this apart

pattern Lookup \key val <- (lookup key -> Just val)

pattern IsMember \val <- (member val -> True)

-- and they get marked with $ when in pattern 
-- (I'm making this up on the tube)

age (Lookup $"Alice" age) = ...

-- Simon's
f p (Lookup $p p) = p

If it helps we could impose a separation between "argument patterns" and patterns.

I want this feature at least once a week ;) so I self-servingly remain +1 if this can be sorted

comment:12 in reply to:  3 Changed 3 months ago by Iceland_jack

Replying to cactus:

The implementation is a straightforward desugaring into pattern synonyms and view patterns

That's how I started the work on pattern synonyms in the first place... spoiler alert: it never is :)

;)

+1 to SPJ on distinguishing pat and expr arguments. In fact, I think they should be distinguished even when introducing them as formal arguments.

Can you elaborate on last part

Note: See TracTickets for help on using tickets.