Zulip Chat Archive
Stream: general
Topic: pattern matching 101
Scott Morrison (Apr 25 2018 at 08:39):
Easy question: how do I do pattern matching against values? Given k : nat, naively I could try writing
match n with | k := something | _ := something_else end
a glorified if n = k then something else something_else, but of course this doesn't work, because Lean doesn't treat the k in the pattern as related to the earlier k.
Am I just meant to use if ... then ... else? Or can I get the pattern matcher to help me?
Kenny Lau (Apr 25 2018 at 08:40):
you need to use if then else. match only deals with constructors.
Scott Morrison (Apr 25 2018 at 08:43):
That's what I feared. How sad. So if I want to write something that given some n where n = k does X, and given any other some n or none does Y... What's the idiomatic way to write this?
Scott Morrison (Apr 25 2018 at 08:43):
(Preferably your answer shouldn't use option.is_some or friends, just pretend option is a bare inductive type with no dressing up.)
Scott Morrison (Apr 25 2018 at 08:44):
In particular, how can I do this without writing the symbol Y twice?
Sebastian Ullrich (Apr 25 2018 at 08:55):
Other languages have pattern guards for this, but Lean doesn't... yet. You'll have to factor Y out into a let.
Sean Leather (Apr 25 2018 at 08:55):
That's what I feared. How sad. So if I want to write something that given
some nwheren = kdoesX, and given any othersome nornonedoesY... What's the idiomatic way to write this?
This sounds like something you'd use pattern match guards for in Haskell:
case n of Just k | n == k -> something _ -> something_else
Kenny Lau (Apr 25 2018 at 08:56):
In particular, how can I do this without writing the symbol
Ytwice?
if o = some k then _ else Y
Scott Morrison (Apr 25 2018 at 08:57):
okay, good, except I've over-minimised of course, and there are lots of other fields that I don't care about matching :-)
Kenny Lau (Apr 25 2018 at 08:58):
so maybe give us more context?
Simon Hudon (Apr 25 2018 at 13:30):
Is it possible that your type is like the following?
inductive my_type | constr : a -> b -> c -> d -> e -> my_type | other : a' -> b' -> my_type
In Haskell, a common advice is to make that two or more types, separate the sum aspect and the product aspect.
Simon Hudon (Apr 25 2018 at 13:31):
Then, you can use selectors on to access whatever part of the product that you care about
Scott Morrison (Apr 25 2018 at 13:33):
hmm, my type
inductive edit_distance_progress (l₁: list α) (l₂: list α) | exactly : ℕ → edit_distance_progress | at_least : ℕ → partial_edit_distance_data α → edit_distance_progress
Scott Morrison (Apr 25 2018 at 13:33):
and I need to check if I have an exactly _ _ k for some specified value of k.
Simon Hudon (Apr 25 2018 at 13:38):
Ok, it's not as bad as I thought. I thought because you didn't want to repeat Y. Is it a pattern for partial_edit_distance_data α?
Scott Morrison (Apr 25 2018 at 13:43):
I'm not sure what you mean. The offending code (which works, just looks gross) is <https://github.com/semorrison/lean-tidy/blob/master/src/tidy/rewrite_search.lean#L64-L84>. You can see lines 72-74 and lines 76-78 are almost identical because of this.
Sean Leather (Apr 25 2018 at 13:49):
Why can't you do something like if update_edit_distance h.distance = exactly _ _ k then ... else ... as Kenny suggested?
Scott Morrison (Apr 25 2018 at 13:51):
Oh... somehow I thought those _s would be a problem, but of course they're not. Thank you!
Scott Morrison (Apr 25 2018 at 13:53):
I will need an extra decidable instance for this. I remember there is some trick for synthesising decidable instances for boring inductive types....? Anyone remember?
Sean Leather (Apr 25 2018 at 13:54):
@[derive decidable_eq] inductive ...
Scott Morrison (Apr 25 2018 at 13:55):
Lovely! And where do I find out what derive is doing? :-)
Sean Leather (Apr 25 2018 at 13:57):
I'm sure there's a #print that'll tell you, but I never remember which one. :blush:
Sean Leather (Apr 25 2018 at 13:58):
Perhaps #print <type-name>.decidable_eq?
Last updated: May 02 2025 at 03:31 UTC