Trait canrun::core::constraints::Constraint
source · pub trait Constraint {
// Required method
fn attempt(&self, state: &State) -> Result<ResolveFn, LVarList>;
}
Expand description
Update a State
whenever one or more crate::LVar
s are resolved.
The Constraint::attempt
function will be run when it is initially added.
Returning a Err([LVarList])
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 LVarList
.
The resolve_1
, resolve_2
, OneOfTwo
and TwoOfThree
helpers can simplify handling this (plus returning the LVarList
).
Example:
use canrun::{State, Unify, Query, Value, LVarList};
use canrun::constraints::{Constraint, resolve_1, ResolveFn};
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, LVarList> {
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]);