Zulip Chat Archive
Stream: new members
Topic: Pattern matching and some constructors simply does not works
Felipe GS (Jun 24 2022 at 11:37):
inductive Lemon : Type 0 → Type 1 where
| pure : t → Lemon t
| seq : Lemon (u → t) → Lemon u → Lemon t
| satisfy : (Char → Bool) → Lemon String
-- tactic 'cases' failed, nested error:
-- dependent elimination failed, failed to solve equation
-- Int = String
-- at case Lemon.satisfy after processing
def test : Lemon Int → Int
| Lemon.pure x => 2
| Lemon.seq x y => 2
Why can't I do that? I tried with casesOn but for some reason the first functions does not unifies with Int so I simply cant remove the value from inside of the pure!
If the result type in the data constructor is different from a type variable, it always fail in a pattern match :\
Reid Barton (Jun 24 2022 at 11:40):
Int
could be equal to String
so Lean cannot eliminate the possibility of Lemon.satisfy
.
Reid Barton (Jun 24 2022 at 11:40):
If you are coming from Haskell, then this will look strange
Felipe GS (Jun 24 2022 at 11:47):
So.. how should I rewrite this code to make something like that work? I think that Lemon.satisfy
is useful so I cannot simply remove this constructor :\
Kevin Buzzard (Jun 24 2022 at 11:53):
Why not just return 37 in the satisfy
case?
Reid Barton (Jun 24 2022 at 12:04):
I guess in a real interpreter you will have to handle all possible type indices anyways (for seq
), like Lemon a -> a
, so this issue won't come up
Felipe GS (Jun 24 2022 at 12:06):
Yeah but I'm trying to make a function to optimize the ast so seq (pure f) (pure x)
becomes pure (f x)
but I cannot pattern match on the first constructor because the type is Lemon (u -> t)
(When I add another constructor | empty : Lemon Unit
)
Felipe GS (Jun 24 2022 at 12:09):
Kevin Buzzard said:
Why not just return 37 in the
satisfy
case?
/--
type mismatch
Lemon.satisfy x
has type
Lemon String : Type 1
but is expected to have type
Lemon Int : Type 1
-/
def test : Lemon Int → Int
| Lemon.seq f x => 1
| Lemon.pure x => 2
| Lemon.satisfy x => 3
Reid Barton (Jun 24 2022 at 12:20):
Not sure how smart the equation compiler is on this sort of thing. This works at least:
def test' : Lemon a → a = Int → Int
| Lemon.seq f x, _ => 1
| Lemon.pure x, _ => 2
| Lemon.satisfy x, _ => 3
def test : Lemon Int → Int
| x => test' x rfl
Reid Barton (Jun 24 2022 at 12:20):
I would need a real example to give a real suggestion.
Reid Barton (Jun 24 2022 at 12:22):
A silly suggestion: If you really wanted to, you could add an axiom saying Int
and String
are distinct (which is certainly consistent) and then use False.elim
in the "impossible" case.
Felipe GS (Jun 24 2022 at 12:24):
How should I fix that?
inductive Lemon : Type 0 → Type 1 where
| pure : t → Lemon t
| seq : Lemon (u → t) → Lemon u → Lemon t
| satisfy : (Char → Bool) → Lemon String
| empty : Lemon Unit
/--
tactic 'cases' failed, nested error:
dependent elimination failed, failed to solve equation
(u✝ → α) = String
at case Lemon.satisfy after processing
(@Lemon.seq _ _ _ (@Lemon.pure _ _))
the dependent pattern matcher can solve the following kinds of equations
-/
def opt : Lemon α → Lemon α
| Lemon.seq (Lemon.pure f) (Lemon.pure x) => Lemon.pure (f x)
| r => r
Reid Barton (Jun 24 2022 at 12:33):
I think the equation compiler just doesn't know how to handle this situation (yet?). Here is one way to do it:
inductive Lemon (a b : Type) : Type 0 → Type 1 where
| pure : t → Lemon a b t
| seq : Lemon a b (u → t) → Lemon a b u → Lemon a b t
| satisfy : (Char → Bool) → Lemon a b a
| empty : Lemon a b b
def opt : Lemon a b α → Lemon a b α
| Lemon.seq (Lemon.pure f) (Lemon.pure x) => Lemon.pure (f x)
| r => r
Reid Barton (Jun 24 2022 at 12:34):
If you need to know a = String
in some other case, you can pass in an equality hypothesis like in test'
Last updated: Dec 20 2023 at 11:08 UTC