pub trait Constraint {
    fn attempt(&self, state: &State) -> Result<ResolveFn, VarWatch>;
Expand description

Update a State whenever one or more LVars 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.


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).


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();
            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]);

Required Methods§

Resolve required variables in a state and resubscribe or request to update the state.