A nondeterminism monad. #
We represent nondeterministic values in a type α
as a single field structure containing an
MLList m (σ × α)
, i.e. as a monadic lazy list of possible values,
each equipped with the backtrackable state
required to run further computations in the ambient monad.
We provide an Alternative
Monad
instance, as well as functions bind
, mapM
, and filterMapM
,
and functions singletonM
, ofListM
, ofOptionM
, and firstM
for entering and leaving the nondeterministic world.
Operations on the nondeterministic value via bind
, mapM
, and filterMapM
run with the appropriate backtrackable state, and are responsible for updating the state themselves
(typically this doesn't need to be done explicitly,
but just happens as a side effect in the monad m
).
Convert a non-deterministic value into a lazy list, keeping the backtrackable state. Be careful that monadic operations on the
MLList
will not respect this state!
Nondet m α
is variation on MLList m α
suitable for use with backtrackable monads m
.
We think of Nondet m α
as a nondeterministic value in α
,
with the possible alternatives stored in a monadic lazy list.
Along with each a : α
we store the backtrackable state, and ensure that monadic operations
on alternatives run with the appropriate state.
Operations on the nondeterministic value via bind
, mapM
, and filterMapM
run with the appropriate backtrackable state, and are responsible for updating the state themselves
(typically this doesn't need to be done explicitly,
but just happens as a side effect in the monad m
).
Instances For
Equations
- Nondet.instInhabitedNondet = { default := Nondet.nil }
Squash a monadic nondeterministic value to a nondeterministic value.
Equations
- Nondet.squash L = { toMLList := MLList.squash fun x => do let __do_lift ← L () pure __do_lift.toMLList }
Instances For
Bind a nondeterministic function over a nondeterministic value, ensuring the function is run with the relevant backtrackable state at each value.
Convert any value in the monad to the singleton nondeterministic value.
Equations
- Nondet.singletonM x = { toMLList := MLList.singletonM do let a ← x let __do_lift ← Lean.saveState pure (a, __do_lift) }
Instances For
Convert a value to the singleton nondeterministic value.
Equations
Instances For
Nondet m
is an alternative monad.
Equations
- Nondet.instAlternativeNondet = Alternative.mk (fun {α} => Nondet.nil) fun {α} x y => { toMLList := MLList.append x.toMLList fun x => (y ()).toMLList }
Equations
- Nondet.instMonadLiftNondet = { monadLift := fun {α} => Nondet.singletonM }
Lift a list of monadic values to a nondeterministic value. We ensure that each monadic value is evaluated with the same backtrackable state.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Lift a list of values to a nondeterministic value. (The backtrackable state in each will be identical: whatever the state was when we first read from the result.)
Equations
- Nondet.ofList L = Nondet.ofListM (List.map pure L)
Instances For
Apply a function which returns values in the monad to every alternative of a Nondet m α
.
Equations
- Nondet.mapM f L = Nondet.bind L fun a => Nondet.singletonM (f a)
Instances For
Apply a function to each alternative in a Nondet m α
.
Equations
- Nondet.map f L = Nondet.mapM (fun a => pure (f a)) L
Instances For
Convert a monadic optional value to a nondeterministic value.
Equations
- Nondet.ofOptionM x = Nondet.squash fun x => do let __do_lift ← x match __do_lift with | none => pure Nondet.nil | some a => pure (Nondet.singleton a)
Instances For
Convert an optional value to a nondeterministic value.
Equations
- Nondet.ofOption x = Nondet.ofOptionM (pure x)
Instances For
Filter and map a nondeterministic value using a monadic function which may return none
.
Equations
- Nondet.filterMapM f L = Nondet.bind L fun a => Nondet.ofOptionM (f a)
Instances For
Filter and map a nondeterministic value.
Equations
- Nondet.filterMap f L = Nondet.filterMapM (fun a => pure (f a)) L
Instances For
Filter a nondeterministic value using a monadic predicate.
Equations
- Nondet.filterM p L = Nondet.filterMapM (fun a => do let __do_lift ← p a if __do_lift.down = true then pure (some a) else pure none) L
Instances For
Filter a nondeterministic value.
Equations
- Nondet.filter p L = Nondet.filterM (fun a => pure { down := p a }) L
Instances For
All iterations of a non-deterministic function on an initial value.
(That is, depth first search.)
Find the first alternative in a nondeterministic value, as a monadic value.
Equations
- Nondet.head L = do let __discr ← MLList.head L.toMLList match __discr with | (x, s) => do Lean.restoreState s pure x
Instances For
Find the value of a monadic function on the first alternative in a nondeterministic value where the function succeeds.
Equations
- Nondet.firstM L f = Nondet.head (Nondet.filterMapM f L)
Instances For
Convert a non-deterministic value into a lazy list, by discarding the backtrackable state.
Equations
- Nondet.toMLList' L = MLList.map (fun x => x.fst) L.toMLList
Instances For
Convert a non-deterministic value into a list in the monad, retaining the backtrackable state.
Equations
- Nondet.toList L = MLList.force L.toMLList
Instances For
Convert a non-deterministic value into a list in the monad, by discarding the backtrackable state.
Equations
- Nondet.toList' L = MLList.force (MLList.map (fun x => x.fst) L.toMLList)