module def f (x : Option Nat) (h : x ≠ none) : Nat := match x with | none => by contradiction | some a => a -- The following should work out-of-the-box with `Option.pbind_some' example (h : b = some a) : (b.pbind fun a h => some <| a + f b (by grind)) = some (a + a) := by grind [f] /-- info: Try these: [apply] grind only [= gen Option.pbind_some', f, #81d1] [apply] grind only [= gen Option.pbind_some', f] [apply] grind => instantiate only [= gen Option.pbind_some'] instantiate only [f] mbtc cases #81d1 -/ #guard_msgs (info) in example (h : b = some a) : (b.pbind fun a h => some <| a + f b (by grind)) = some (a + a) := by grind? [f] reset_grind_attrs% @[grind gen] theorem pbind_some' {α β} {x : Option α} {a : α} {f : (a : α) → x = some a → Option β} (h : x = some a) : Option.pbind x f = f a h := by subst h; rfl example (h : b = some a) : (b.pbind fun a h => some <| a + f b (by grind)) = some (a + a) := by grind only [gen pbind_some', f] -- Note that the following instance does not have hypotheses. /-- trace: [grind.ematch.instance] pbind_some': (b.pbind fun a h => some (2 * a)) = some (2 * a) -/ #guard_msgs (trace) in example (a : Nat) (h : b = some a) : (b.pbind fun a h => some <| 2*a) = some (a + a) := by set_option trace.grind.ematch.instance true in grind only [gen pbind_some'] /-- trace: [grind.ematch.instance] pbind_some': (b.pbind fun a h => some (a + f b ⋯)) = some (a + f b ⋯) [grind.ematch.instance] f.eq_2: f (some a) ⋯ = a -/ #guard_msgs (trace) in example (h : b = some a) : (b.pbind fun a h => some <| a + f b (by grind)) = some (a + a) := by set_option trace.grind.ematch.instance true in grind [f] -- Many different instances are generated if the `gen` modifier is not used /- trace: [grind.ematch.instance] pbind_some': ∀ (h : b = some a), (b.pbind fun a h => some (a + f b ⋯)) = some (a + f b ⋯) [grind.ematch.instance] pbind_some': ∀ (h : b = some (2 * a)), (b.pbind fun a h => some (a + f b ⋯)) = some (2 * a + f b ⋯) [grind.ematch.instance] pbind_some': ∀ (h_2 : b = some (a + f b ⋯)), (b.pbind fun a h => some (a + f b ⋯)) = some (a + f b ⋯ + f b ⋯) [grind.ematch.instance] f.eq_2: f (some a) ⋯ = a [grind.ematch.instance] pbind_some': ∀ (h_2 : b = some (a + 2 * f b ⋯)), (b.pbind fun a h => some (a + f b ⋯)) = some (a + 2 * f b ⋯ + f b ⋯) [grind.ematch.instance] pbind_some': ∀ (h_2 : b = some (a + 3 * f b ⋯)), (b.pbind fun a h => some (a + f b ⋯)) = some (a + 3 * f b ⋯ + f b ⋯) [grind.ematch.instance] pbind_some': ∀ (h_2 : b = some (a + 4 * f b ⋯)), (b.pbind fun a h => some (a + f b ⋯)) = some (a + 4 * f b ⋯ + f b ⋯) [grind.ematch.instance] pbind_some': ∀ (h_3 : b = some (a + 5 * f b ⋯)), (b.pbind fun a h => some (a + f b ⋯)) = some (a + 5 * f b ⋯ + f b ⋯) [grind.ematch.instance] pbind_some': ∀ (h_3 : b = some (a + 6 * f b ⋯)), (b.pbind fun a h => some (a + f b ⋯)) = some (a + 6 * f b ⋯ + f b ⋯) [grind.ematch.instance] pbind_some': ∀ (h_3 : b = some (a + 7 * f b ⋯)), (b.pbind fun a h => some (a + f b ⋯)) = some (a + 7 * f b ⋯ + f b ⋯) [grind.ematch.instance] pbind_some': ∀ (h_3 : b = some (a + 5 * f b ⋯)), (b.pbind fun a h => some (a + f b ⋯)) = some (a + 5 * f b ⋯ + f b ⋯) [grind.ematch.instance] pbind_some': ∀ (h_3 : b = some (a + 6 * f b ⋯)), (b.pbind fun a h => some (a + f b ⋯)) = some (a + 6 * f b ⋯ + f b ⋯) [grind.ematch.instance] pbind_some': ∀ (h_3 : b = some (a + 7 * f b ⋯)), (b.pbind fun a h => some (a + f b ⋯)) = some (a + 7 * f b ⋯ + f b ⋯) -/ -- #guard_msgs (trace) in -- TODO: investigate nondet behavior in this test. It is probably due -- to semiring support in `ring` module. It may not be hashconsing terms example (h : b = some a) : (b.pbind fun a h => some <| a + f b (by grind)) = some (a + a) := by set_option trace.grind.ematch.instance true in grind only [pbind_some', f] -- `Option.pbind_some` produces an instance with a `cast` that makes the result hard to use /-- trace: [grind.ematch.instance] Option.pbind_some: (some a).pbind (cast ⋯ fun a h => some (a + f b ⋯)) = cast ⋯ (fun a h => some (a + f b ⋯)) a ⋯ [grind.ematch.instance] Option.pbind_some: (some (2 * a)).pbind (cast ⋯ fun a h => some (a + f b ⋯)) = cast ⋯ (fun a h => some (a + f b ⋯)) (2 * a) ⋯ -/ #guard_msgs (trace) in example (h : b = some a) : (b.pbind fun a h => some <| a + f b (by grind)) = some (a + a) := by set_option trace.grind.ematch.instance true in fail_if_success grind only [Option.pbind_some, f] sorry /-- trace: [grind.ematch.instance] pbind_some': (b.pbind fun a _h => some (2 * a)) = some (2 * a) -/ #guard_msgs (trace) in example (a : Nat) (h : b = some a) : (b.pbind fun a _h => some <| 2*a) = some (a + a) := by set_option trace.grind.ematch.instance true in grind only [= gen pbind_some'] example (a : Nat) (h : b = some a) : (b.pbind fun a h => some <| 2*a) = some (a + a) := by fail_if_success grind only [= pbind_some'] sorry reset_grind_attrs% @[grind = gen] theorem pbind_some'' {α β} {x : Option α} {a : α} {f : (a : α) → x = some a → Option β} (h : x = some a) : Option.pbind x f = f a h := by subst h; rfl /-- trace: [grind.ematch.instance] pbind_some'': (b.pbind fun a h => some (a + f b ⋯)) = some (a + f b ⋯) [grind.ematch.instance] f.eq_2: f (some a) ⋯ = a -/ #guard_msgs (trace) in example (h : b = some a) : (b.pbind fun a h => some <| a + f b (by grind)) = some (a + a) := by set_option trace.grind.ematch.instance true in grind [f] reset_grind_attrs% @[grind =_ gen] theorem pbind_some''' {α β} {x : Option α} {a : α} {f : (a : α) → x = some a → Option β} (h : x = some a) : f a h = Option.pbind x f := by subst h; rfl /-- trace: [grind.ematch.instance] pbind_some''': some (a + f b ⋯) = b.pbind fun a h => some (a + f b ⋯) [grind.ematch.instance] f.eq_2: f (some a) ⋯ = a -/ #guard_msgs (trace) in example (h : b = some a) : (b.pbind fun a h => some <| a + f b (by grind)) = some (a + a) := by set_option trace.grind.ematch.instance true in grind [f]