/- Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura -/ prelude import init.data.list.lemmas import init.meta.mk_dec_eq_instance open list universes u v local attribute [simp] join ret instance : monad list := {pure := @list.ret, bind := @list.bind, id_map := begin intros _ xs, induction xs with x xs ih, { refl }, { dsimp [function.comp] at ih, dsimp [function.comp], simp [*] } end, pure_bind := by simp_intros, bind_assoc := begin intros _ _ _ xs _ _, induction xs, { refl }, { simp [*] } end} instance : alternative list := { failure := @list.nil, orelse := @list.append, ..list.monad } namespace list variables {α β : Type u} (p : α → Prop) [decidable_pred p] instance bin_tree_to_list : has_coe (bin_tree α) (list α) := ⟨bin_tree.to_list⟩ instance decidable_bex : ∀ (l : list α), decidable (∃ x ∈ l, p x) | [] := is_false (by simp) | (x::xs) := if h₁ : p x then is_true ⟨x, mem_cons_self _ _, h₁⟩ else match decidable_bex xs with | is_true h₂ := is_true begin cases h₂ with y h, cases h with hm hp, exact ⟨y, mem_cons_of_mem _ hm, hp⟩ end | is_false h₂ := is_false begin intro h, cases h with y h, cases h with hm hp, cases eq_or_mem_of_mem_cons hm, { rw [h] at hp, contradiction }, { refine absurd _ h₂, exact ⟨y, h, hp⟩ } end end instance decidable_ball (l : list α) : decidable (∀ x ∈ l, p x) := if h : ∃ x ∈ l, ¬ p x then is_false $ let ⟨x, h, np⟩ := h in λ al, np (al x h) else is_true $ λ x hx, if h' : p x then h' else false.elim $ h ⟨x, hx, h'⟩ end list