feat(library/init): add 'guard' and helper typeclasses
This commit is contained in:
parent
60c4384d09
commit
02fb2c9c8a
11 changed files with 125 additions and 40 deletions
22
library/init/alternative.lean
Normal file
22
library/init/alternative.lean
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/-
|
||||
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.logic init.applicative
|
||||
|
||||
structure alternative [class] (f : Type → Type) extends applicative f :=
|
||||
(failure : Π {A : Type}, f A)
|
||||
(orelse : Π {A : Type}, f A → f A → f A)
|
||||
|
||||
inline definition failure {f : Type → Type} [alternative f] {A : Type} : f A :=
|
||||
alternative.failure f
|
||||
|
||||
inline definition orelse {f : Type → Type} [alternative f] {A : Type} : f A → f A → f A :=
|
||||
alternative.orelse
|
||||
|
||||
infixr ` <|> `:2 := orelse
|
||||
|
||||
inline definition guard {f : Type₁ → Type} [alternative f] (p : Prop) [decidable p] : f unit :=
|
||||
if p then pure () else failure
|
||||
19
library/init/applicative.lean
Normal file
19
library/init/applicative.lean
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/-
|
||||
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.functor
|
||||
|
||||
structure applicative [class] (f : Type → Type) extends functor f :=
|
||||
(pure : Π {A : Type}, A → f A)
|
||||
(seq : Π {A B : Type}, f (A → B) → f A → f B)
|
||||
|
||||
inline definition pure {f : Type → Type} [applicative f] {A : Type} (a : A) : f A :=
|
||||
applicative.pure f a
|
||||
|
||||
inline definition seq_app {A B : Type} {f : Type → Type} [applicative f] (g : f (A → B)) (a : f A) : f B :=
|
||||
applicative.seq g a
|
||||
|
||||
infixr ` <*> `:2 := seq_app
|
||||
|
|
@ -9,6 +9,6 @@ import init.relation init.nat init.prod init.combinator
|
|||
import init.bool init.num init.sigma init.measurable init.setoid init.quot
|
||||
import init.funext init.function init.subtype init.classical init.simplifier
|
||||
import init.monad init.option init.fin init.list init.char init.string init.to_string
|
||||
import init.timeit init.trace init.unsigned init.ordering
|
||||
import init.timeit init.trace init.unsigned init.ordering init.list_classes
|
||||
import init.meta
|
||||
import init.wf init.wf_k init.sigma_lex
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ definition reverse : list A → list A
|
|||
definition map {B : Type} (f : A → B) : list A → list B
|
||||
| [] := []
|
||||
| (a :: l) := f a :: map l
|
||||
|
||||
definition join : list (list A) → list A
|
||||
| [] := []
|
||||
| (l :: ls) := append l (join ls)
|
||||
end list
|
||||
|
||||
definition list_has_append [instance] {A : Type} : has_append (list A) :=
|
||||
|
|
|
|||
23
library/init/list_classes.lean
Normal file
23
library/init/list_classes.lean
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/-
|
||||
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.monad init.alternative
|
||||
open list
|
||||
|
||||
inline definition list_fmap {A B : Type} (f : A → B) (l : list A) : list B :=
|
||||
map f l
|
||||
|
||||
inline definition list_bind {A B : Type} (a : list A) (b : A → list B) : list B :=
|
||||
join (map b a)
|
||||
|
||||
inline definition list_return {A : Type} (a : A) : list A :=
|
||||
[a]
|
||||
|
||||
definition list_is_monad [instance] : monad list :=
|
||||
monad.mk @list_fmap @list_return @list_bind
|
||||
|
||||
definition list_is_alternative [instance] : alternative list :=
|
||||
alternative.mk @list_fmap @list_return (@fapp _ _) @nil @list.append
|
||||
|
|
@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
|||
Authors: Leonardo de Moura
|
||||
-/
|
||||
prelude
|
||||
import init.monad init.meta.exceptional init.meta.format
|
||||
import init.monad init.alternative init.meta.exceptional init.meta.format
|
||||
/-
|
||||
Remark: we use a function that produces a format object as the exception information.
|
||||
Motivation: the formatting object may be big, and we may create it on demand.
|
||||
|
|
@ -47,35 +47,35 @@ inline protected meta_definition bind (t₁ : base_tactic S A) (t₂ : A → bas
|
|||
|
||||
inline protected meta_definition return (a : A) : base_tactic S A :=
|
||||
λ s, success a s
|
||||
|
||||
end base_tactic
|
||||
|
||||
meta_definition base_tactic.is_monad [instance] (S : Type) : monad (base_tactic S) :=
|
||||
monad.mk (@base_tactic.fmap S) (@base_tactic.return S) (@base_tactic.bind S)
|
||||
|
||||
namespace tactic
|
||||
variables {S A : Type}
|
||||
open base_tactic_result
|
||||
|
||||
meta_definition fail {A B : Type} [has_to_format B] (msg : B) : base_tactic S A :=
|
||||
λ s, exception A (λ u, to_fmt msg) s
|
||||
|
||||
meta_definition failed : base_tactic S A :=
|
||||
fail "failed"
|
||||
|
||||
meta_definition try (t : base_tactic S A) : base_tactic S unit :=
|
||||
λ s, base_tactic_result.cases_on (t s)
|
||||
(λ a, success ())
|
||||
(λ e s', success () s)
|
||||
|
||||
meta_definition or_else (t₁ t₂ : base_tactic S A) : base_tactic S A :=
|
||||
meta_definition tactic_orelse {S A : Type} (t₁ t₂ : base_tactic S A) : base_tactic S A :=
|
||||
λ s, base_tactic_result.cases_on (t₁ s)
|
||||
success
|
||||
(λ e₁ s', base_tactic_result.cases_on (t₂ s)
|
||||
success
|
||||
(exception A))
|
||||
|
||||
infix `<|>`:1 := or_else
|
||||
meta_definition base_tactic_is_monad [instance] (S : Type) : monad (base_tactic S) :=
|
||||
monad.mk (@base_tactic.fmap S) (@base_tactic.return S) (@base_tactic.bind S)
|
||||
|
||||
meta_definition tactic.fail {S A B : Type} [has_to_format B] (msg : B) : base_tactic S A :=
|
||||
λ s, exception A (λ u, to_fmt msg) s
|
||||
|
||||
meta_definition tactic.failed {S A : Type} : base_tactic S A :=
|
||||
tactic.fail "failed"
|
||||
|
||||
meta_definition base_tactic_is_alternative [instance] (S : Type) : alternative (base_tactic S) :=
|
||||
alternative.mk (@base_tactic.fmap S) (λ A a s, success a s) (@fapp _ _) (@tactic.failed S) (@tactic_orelse S)
|
||||
|
||||
namespace tactic
|
||||
variables {S A : Type}
|
||||
|
||||
meta_definition try (t : base_tactic S A) : base_tactic S unit :=
|
||||
λ s, base_tactic_result.cases_on (t s)
|
||||
(λ a, success ())
|
||||
(λ e s', success () s)
|
||||
|
||||
meta_definition skip : base_tactic S unit :=
|
||||
success ()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
|||
Authors: Luke Nelson and Jared Roesch
|
||||
-/
|
||||
prelude
|
||||
import init.functor init.string init.trace
|
||||
import init.applicative init.string init.trace
|
||||
|
||||
structure monad [class] (m : Type → Type) extends functor m : Type :=
|
||||
(ret : Π {a:Type}, a → m a)
|
||||
|
|
@ -13,14 +13,16 @@ structure monad [class] (m : Type → Type) extends functor m : Type :=
|
|||
inline definition return {m : Type → Type} [monad m] {A : Type} (a : A) : m A :=
|
||||
monad.ret m a
|
||||
|
||||
inline definition fapp {A B : Type} {m : Type → Type} [monad m] (f : m (A → B)) (a : m A) : m B :=
|
||||
definition fapp {m : Type → Type} [monad m] {A B : Type} (f : m (A → B)) (a : m A) : m B :=
|
||||
do g ← f,
|
||||
b ← a,
|
||||
return (g b)
|
||||
|
||||
inline definition monad_is_applicative [instance] (m : Type → Type) [monad m] : applicative m :=
|
||||
applicative.mk (@monad.map _ _) (@monad.ret _ _) (@fapp _ _)
|
||||
|
||||
inline definition monad.and_then {A B : Type} {m : Type → Type} [monad m] (a : m A) (b : m B) : m B :=
|
||||
do a, b
|
||||
|
||||
infixr ` <*> `:2 := fapp
|
||||
infixl ` >>= `:2 := monad.bind
|
||||
infixl ` >> `:2 := monad.and_then
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Authors: Leonardo de Moura
|
|||
Basic datatypes
|
||||
-/
|
||||
prelude
|
||||
import init.logic init.monad
|
||||
import init.logic init.monad init.alternative
|
||||
|
||||
open decidable
|
||||
|
||||
|
|
@ -23,20 +23,23 @@ definition option_has_decidable_eq [instance] {A : Type} [H : decidable_eq A] :
|
|||
| ff n := ff (λ H, option.no_confusion H (λ e, absurd e n))
|
||||
end
|
||||
|
||||
namespace option
|
||||
inline protected definition fmap {A B : Type} (f : A → B) (e : option A) : option B :=
|
||||
option.cases_on e
|
||||
none
|
||||
(λ a, some (f a))
|
||||
inline definition option_fmap {A B : Type} (f : A → B) (e : option A) : option B :=
|
||||
option.cases_on e
|
||||
none
|
||||
(λ a, some (f a))
|
||||
|
||||
inline protected definition bind {A B : Type} (a : option A) (b : A → option B) : option B :=
|
||||
option.cases_on a
|
||||
none
|
||||
(λ a, b a)
|
||||
inline definition option_bind {A B : Type} (a : option A) (b : A → option B) : option B :=
|
||||
option.cases_on a
|
||||
none
|
||||
(λ a, b a)
|
||||
|
||||
inline protected definition return {A : Type} (a : A) : option A :=
|
||||
some a
|
||||
end option
|
||||
definition option_is_monad [instance] : monad option :=
|
||||
monad.mk @option_fmap @some @option_bind
|
||||
|
||||
definition option.is_monad [instance] : monad option :=
|
||||
monad.mk @option.fmap @option.return @option.bind
|
||||
definition option_orelse {A : Type} : option A → option A → option A
|
||||
| (some a) _ := some a
|
||||
| none (some a) := some a
|
||||
| none none := none
|
||||
|
||||
definition option_is_alternative [instance] {A : Type} : alternative option :=
|
||||
alternative.mk @option_fmap @some (@fapp _ _) @none @option_orelse
|
||||
|
|
|
|||
7
tests/lean/list_monad1.lean
Normal file
7
tests/lean/list_monad1.lean
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
vm_eval
|
||||
(do {
|
||||
a : nat ← [1, 2, 3, 4],
|
||||
b : nat ← [4, 5, 6],
|
||||
(guard $ 2 * a ≥ b : list unit),
|
||||
(guard $ b < 6 : list unit),
|
||||
return (a, b) } : list (nat × nat) )
|
||||
1
tests/lean/list_monad1.lean.expected.out
Normal file
1
tests/lean/list_monad1.lean.expected.out
Normal file
|
|
@ -0,0 +1 @@
|
|||
[(2, 4), (3, 4), (3, 5), (4, 4), (4, 5)]
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
alternative : (Type → Type) → Type
|
||||
applicative : (Type → Type) → Type
|
||||
decidable : Prop → Type₁
|
||||
functor : (Type → Type) → Type
|
||||
has_add : Type → Type
|
||||
|
|
@ -26,6 +28,8 @@ point : Type → Type → Type
|
|||
setoid : Type → Type
|
||||
subsingleton : Type → Prop
|
||||
well_founded : Π {A}, (A → A → Prop) → Prop
|
||||
alternative : (Type → Type) → Type
|
||||
applicative : (Type → Type) → Type
|
||||
decidable : Prop → Type₁
|
||||
functor : (Type → Type) → Type
|
||||
has_add : Type → Type
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue