Trait canrun::core::Unify

source ·
pub trait Unify: Any + Debug {
    // Required method
    fn unify(state: State, a: Rc<Self>, b: Rc<Self>) -> Option<State>;
}
Expand description

How compatible values are matched with each other.

See Unification for a formal and probably more correct definition. This will attempt to describe unification as implemented (and understood by me).

The simplest example of unification looks like equality or variable assignment. In x=1, if the variable x is unbound, the statement succeeds and x is considered equal to 1. 1=1 is also valid, though slightly silly. Unification does not care about direction, so 1=x is equally valid and has the same effect.

A follow-up assertion that x=2 would fail, because x is already bound to 1.

Unifying structures containing other types of values can get interesting very fast. Unifying a free (unbound) variable with a structure simply binds that variable to the entire structure (e.g. x=(1,2)). However, binding two compatible structures with each other allows binding to values inside the structures. In (x,2)=(1,2), the x in the first structure is bound to the 1 in the second. Structurally incompatible values will fail immediately: (x,2,3)=(1,2).

Arbitrarily nested structures can be unified by recursively applying this simple pattern matching.

For simple types, unification is essentially the same thing as equality (and implementations are provided for most simple primitive types). The general pattern for structures is to define a way to match up their component parts and recursively attempt to unify them.

Implementation

Default implementations are provided for most primitive types, and a few general “logic collections”. You can also implement it for your own types.

TODO: Create a derive macro

use canrun::core::{State, Unify, Value};
use std::rc::Rc;

#[derive(Debug)]
struct MyType<T: Unify> {
    inside: Value<T>
}

impl<T: Unify> Unify for MyType<T> {
    fn unify(state: State, a: Rc<Self>, b: Rc<Self> ) -> Option<State> {
        state.unify(&a.inside, &b.inside)
    }
}

Required Methods§

source

fn unify(state: State, a: Rc<Self>, b: Rc<Self>) -> Option<State>

Attempt to unify two fully resolved values.

This function accepts Rc<T>s to simplify the borrow checking. The Option<_> return type allows recursive unification of structures that hold additional values.

Implementations on Foreign Types§

source§

impl Unify for i16

source§

fn unify(state: State, a: Rc<i16>, b: Rc<i16>) -> Option<State>

source§

impl Unify for isize

source§

fn unify(state: State, a: Rc<isize>, b: Rc<isize>) -> Option<State>

source§

impl Unify for char

source§

fn unify(state: State, a: Rc<char>, b: Rc<char>) -> Option<State>

source§

impl Unify for i32

source§

fn unify(state: State, a: Rc<i32>, b: Rc<i32>) -> Option<State>

source§

impl Unify for u16

source§

fn unify(state: State, a: Rc<u16>, b: Rc<u16>) -> Option<State>

source§

impl Unify for String

source§

fn unify(state: State, a: Rc<String>, b: Rc<String>) -> Option<State>

source§

impl<Av, Bv, Cv> Unify for (Value<Av>, Value<Bv>, Value<Cv>)where Av: Unify, Bv: Unify, Cv: Unify,

source§

fn unify(state: State, l: Rc<Self>, r: Rc<Self>) -> Option<State>

source§

impl Unify for u8

source§

fn unify(state: State, a: Rc<u8>, b: Rc<u8>) -> Option<State>

source§

impl<Av, Bv, Cv, Dv, Ev> Unify for (Value<Av>, Value<Bv>, Value<Cv>, Value<Dv>, Value<Ev>)where Av: Unify, Bv: Unify, Cv: Unify, Dv: Unify, Ev: Unify,

source§

fn unify(state: State, l: Rc<Self>, r: Rc<Self>) -> Option<State>

source§

impl Unify for f32

source§

fn unify(state: State, a: Rc<f32>, b: Rc<f32>) -> Option<State>

source§

impl<Av, Bv> Unify for (Value<Av>, Value<Bv>)where Av: Unify, Bv: Unify,

source§

fn unify(state: State, l: Rc<Self>, r: Rc<Self>) -> Option<State>

source§

impl Unify for &'static str

source§

fn unify( state: State, a: Rc<&'static str>, b: Rc<&'static str> ) -> Option<State>

source§

impl Unify for u32

source§

fn unify(state: State, a: Rc<u32>, b: Rc<u32>) -> Option<State>

source§

impl Unify for usize

source§

fn unify(state: State, a: Rc<usize>, b: Rc<usize>) -> Option<State>

source§

impl<Av, Bv, Cv, Dv> Unify for (Value<Av>, Value<Bv>, Value<Cv>, Value<Dv>)where Av: Unify, Bv: Unify, Cv: Unify, Dv: Unify,

source§

fn unify(state: State, l: Rc<Self>, r: Rc<Self>) -> Option<State>

source§

impl Unify for f64

source§

fn unify(state: State, a: Rc<f64>, b: Rc<f64>) -> Option<State>

source§

impl Unify for Range<usize>

source§

fn unify( state: State, a: Rc<Range<usize>>, b: Rc<Range<usize>> ) -> Option<State>

source§

impl Unify for u64

source§

fn unify(state: State, a: Rc<u64>, b: Rc<u64>) -> Option<State>

source§

impl Unify for i8

source§

fn unify(state: State, a: Rc<i8>, b: Rc<i8>) -> Option<State>

source§

impl Unify for bool

source§

fn unify(state: State, a: Rc<bool>, b: Rc<bool>) -> Option<State>

source§

impl Unify for i64

source§

fn unify(state: State, a: Rc<i64>, b: Rc<i64>) -> Option<State>

Implementors§

source§

impl<K: Unify + Eq + Hash + Debug, V: Unify + Debug> Unify for LMap<K, V>

source§

impl<T: Unify> Unify for LVec<T>