41 lines
1.3 KiB
Text
41 lines
1.3 KiB
Text
/-
|
||
Copyright (c) 2021 Microsoft Corporation. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Leonardo de Moura
|
||
-/
|
||
import Lean.MonadEnv
|
||
|
||
namespace Lean
|
||
|
||
structure LazyInitExtension (m : Type → Type) (α : Type) where
|
||
ext : EnvExtension (Option α)
|
||
fn : m α
|
||
|
||
instance [Monad m] [Inhabited α] : Inhabited (LazyInitExtension m α) where
|
||
default := {
|
||
ext := default
|
||
fn := pure default
|
||
}
|
||
|
||
/--
|
||
Register an environment extension for storing the result of `fn`.
|
||
We initialize the extension with `none`, and `fn` is executed the
|
||
first time `LazyInit.get` is executed.
|
||
|
||
This kind of extension is useful for avoiding work duplication in
|
||
scenarios where a thunk cannot be used because the computation depends
|
||
on state from the `m` monad. For example, we may want to "cache" a collection
|
||
of theorems as a `SimpLemmas` object. -/
|
||
def registerLazyInitExtension (fn : m α) : IO (LazyInitExtension m α) := do
|
||
let ext ← registerEnvExtension (pure none)
|
||
return { ext, fn }
|
||
|
||
def LazyInitExtension.get [MonadEnv m] [Monad m] (init : LazyInitExtension m α) : m α := do
|
||
match init.ext.getState (← getEnv) with
|
||
| some a => return a
|
||
| none =>
|
||
let a ← init.fn
|
||
modifyEnv fun env => init.ext.setState env (some a)
|
||
return a
|
||
|
||
end Lean
|