This PR changes the interface of the `ForIn`, `ForIn'`, and `ForM` typeclasses to not take a `Monad m` parameter. This is a breaking change for most downstream `instance`s, which will will now need to assume `[Monad m]`. The rationale is that if the provider of an instance requires `m` to be a Monad, they should assume this up front. This makes it possible for the instanve to assume `LawfulMonad m` or some other stronger requirement, and also to provided a concrete instance for a particular `m` without assuming a non-canonical `Monad` structure on it. Zulip: [#lean4 > Monad assumptions in fields of other typeclasses @ 💬](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Monad.20assumptions.20in.20fields.20of.20other.20typeclasses/near/537102158)
55 lines
1.3 KiB
Text
55 lines
1.3 KiB
Text
/-
|
|
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
Authors: Leonardo de Moura
|
|
-/
|
|
module
|
|
|
|
prelude
|
|
public import Init.Core
|
|
|
|
public section
|
|
|
|
/-!
|
|
# Notation for `while` and `repeat` loops.
|
|
-/
|
|
|
|
namespace Lean
|
|
|
|
/-! # `repeat` and `while` notation -/
|
|
|
|
inductive Loop where
|
|
| mk
|
|
|
|
@[inline]
|
|
partial def Loop.forIn {β : Type u} {m : Type u → Type v} [Monad m] (_ : Loop) (init : β) (f : Unit → β → m (ForInStep β)) : m β :=
|
|
let rec @[specialize] loop (b : β) : m β := do
|
|
match ← f () b with
|
|
| ForInStep.done b => pure b
|
|
| ForInStep.yield b => loop b
|
|
loop init
|
|
|
|
instance [Monad m] : ForIn m Loop Unit where
|
|
forIn := Loop.forIn
|
|
|
|
syntax "repeat " doSeq : doElem
|
|
|
|
macro_rules
|
|
| `(doElem| repeat $seq) => `(doElem| for _ in Loop.mk do $seq)
|
|
|
|
syntax "while " ident " : " termBeforeDo " do " doSeq : doElem
|
|
|
|
macro_rules
|
|
| `(doElem| while $h : $cond do $seq) => `(doElem| repeat if $h : $cond then $seq else break)
|
|
|
|
syntax "while " termBeforeDo " do " doSeq : doElem
|
|
|
|
macro_rules
|
|
| `(doElem| while $cond do $seq) => `(doElem| repeat if $cond then $seq else break)
|
|
|
|
syntax "repeat " doSeq ppDedent(ppLine) "until " term : doElem
|
|
|
|
macro_rules
|
|
| `(doElem| repeat $seq until $cond) => `(doElem| repeat do $seq:doSeq; if $cond then break)
|
|
|
|
end Lean
|