Opened 2 years ago

Last modified 5 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
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


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 (9)

comment:1 Changed 2 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


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 2 years ago by cactus

Cc: cactus added

comment:3 Changed 2 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 2 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 2 years ago by cactus

Keywords: PatternSynonyms added; patterns pattern synonyms removed

comment:6 Changed 2 years ago by thoughtpolice


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 18 months ago by thoughtpolice


Milestone renamed

comment:8 Changed 13 months ago by thomie

Milestone: 8.0.1

comment:9 Changed 5 months ago by RyanGlScott

Cc: RyanGlScott added
Note: See TracTickets for help on using tickets.