Trait canrun::core::constraints::Constraint
source · Expand description
Update a State
whenever one or more LVar
s are resolved.
The Constraint::attempt
function will be run when it is initially added.
Returning a Err([VarWatch])
signals that the constraint is not
satisfied. The constraint will be re-attempted when one of the specified
variables is bound to another value.
You probably want to use the higher level goal projection functions.
NOTE:
The attempt
function must take care to fully
resolve any variables before creating a VarWatch
.
The resolve_1
, resolve_2
, OneOfTwo
and TwoOfThree
helpers can simplify handling this (plus returning the VarWatch
).
Example:
use canrun::{State, Unify, Query, Value};
use canrun::constraints::{Constraint, resolve_1, ResolveFn, VarWatch};
use std::rc::Rc;
struct Assert<T: Unify> {
val: Value<T>,
assert: Rc<dyn Fn(&T) -> bool>,
}
impl<T: Unify> Constraint for Assert<T>
{
fn attempt(&self, state: &State) -> Result<ResolveFn, VarWatch> {
let resolved = resolve_1(&self.val, state)?;
let assert = self.assert.clone();
Ok(Box::new(
move |state: State| if assert(&*resolved) { Some(state) } else { None },
))
}
}
let x = Value::var();
let state = State::new();
let state = state.constrain(Rc::new(Assert {val: x.clone(), assert: Rc::new(|x| x > &1)}));
let state = state?.unify(&x, &Value::new(2));
let results: Vec<i32> = state.query(x).collect();
assert_eq!(results, vec![2]);