28 lines
857 B
Text
28 lines
857 B
Text
/-
|
||
Copyright (c) 2022 Mac Malone. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Mac Malone
|
||
-/
|
||
|
||
namespace Lake
|
||
|
||
/-- A sequence of calls donated by the key type `κ`. -/
|
||
abbrev CallStack κ := List κ
|
||
|
||
/-- A `CallStack` ending in a cycle. -/
|
||
abbrev Cycle κ := CallStack κ
|
||
|
||
/-- A transformer that equips a monad with a `CallStack` to detect cycles. -/
|
||
abbrev CycleT κ m := ReaderT (CallStack κ) <| ExceptT (Cycle κ) m
|
||
|
||
/--
|
||
Add `key` to the monad's `CallStack` before invoking `act`.
|
||
If adding `key` produces a cycle, the cyclic call stack is thrown.
|
||
-/
|
||
@[inline] def guardCycle [BEq κ] [Monad m]
|
||
(key : κ) (act : CycleT κ m α) : CycleT κ m α := do
|
||
let parents ← read
|
||
if parents.contains key then
|
||
throw <| key :: (parents.partition (· != key)).1 ++ [key]
|
||
else
|
||
act (key :: parents)
|