[][src]Trait canrun::UnifyIn

pub trait UnifyIn<'a, D: DomainType<'a, Self>>: Sized + Debug {
    fn unify_resolved(
        state: State<'a, D>,
        a: Rc<Self>,
        b: Rc<Self>
    ) -> Option<State<'a, D>>; }

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

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.

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 these simplest cases). 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 some collections. You can also implement it for your own types.

TODO: Create a derive macro

use canrun::{State, DomainType, UnifyIn};
use std::rc::Rc;

#[derive(PartialEq, Debug)]
struct MyType;

impl<'a, D> UnifyIn<'a, D> for MyType
where
    // The domain must be constrained to
    // those that contain yur type
    D: DomainType<'a, Self>
{
    fn unify_resolved(
        state: State<'a, D>,
        a: Rc<Self>,
        b: Rc<Self>
    ) -> Option<State<'a, D>> {
        if a == b { Some(state) } else { None }
    }
}

Because the trait is parameterized with a domain, you should be able to implement UnifyIn for third-party types without running into the orphan trait rule, so long as you don't conflict with an existing implementation.

use canrun::{State, DomainType, UnifyIn};
use std::rc::Rc;

canrun::domain! {
    MyDomain {
        SomeForeignType
    }
}

impl<'a> UnifyIn<'a, MyDomain> for SomeForeignType {
    // ...
}

Required methods

fn unify_resolved(
    state: State<'a, D>,
    a: Rc<Self>,
    b: Rc<Self>
) -> Option<State<'a, D>>

Attempt to unify two fully resolved values.

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

Loading content...

Implementations on Foreign Types

impl<'a, D: DomainType<'a, i8>> UnifyIn<'a, D> for i8[src]

impl<'a, D: DomainType<'a, i16>> UnifyIn<'a, D> for i16[src]

impl<'a, D: DomainType<'a, i32>> UnifyIn<'a, D> for i32[src]

impl<'a, D: DomainType<'a, i64>> UnifyIn<'a, D> for i64[src]

impl<'a, D: DomainType<'a, u8>> UnifyIn<'a, D> for u8[src]

impl<'a, D: DomainType<'a, u16>> UnifyIn<'a, D> for u16[src]

impl<'a, D: DomainType<'a, u32>> UnifyIn<'a, D> for u32[src]

impl<'a, D: DomainType<'a, u64>> UnifyIn<'a, D> for u64[src]

impl<'a, D: DomainType<'a, isize>> UnifyIn<'a, D> for isize[src]

impl<'a, D: DomainType<'a, usize>> UnifyIn<'a, D> for usize[src]

impl<'a, D: DomainType<'a, f32>> UnifyIn<'a, D> for f32[src]

impl<'a, D: DomainType<'a, f64>> UnifyIn<'a, D> for f64[src]

impl<'a, D: DomainType<'a, String>> UnifyIn<'a, D> for String[src]

impl<'a, D: DomainType<'a, &'static str>> UnifyIn<'a, D> for &'static str[src]

impl<'a, D: DomainType<'a, bool>> UnifyIn<'a, D> for bool[src]

impl<'a, D: DomainType<'a, char>> UnifyIn<'a, D> for char[src]

impl<'a, Av, Bv, D> UnifyIn<'a, D> for (Val<Av>, Val<Bv>) where
    Av: UnifyIn<'a, D>,
    Bv: UnifyIn<'a, D>,
    D: DomainType<'a, Av> + DomainType<'a, Bv> + DomainType<'a, Self>, 
[src]

impl<'a, Av, Bv, Cv, D> UnifyIn<'a, D> for (Val<Av>, Val<Bv>, Val<Cv>) where
    Av: UnifyIn<'a, D>,
    Bv: UnifyIn<'a, D>,
    Cv: UnifyIn<'a, D>,
    D: DomainType<'a, Av> + DomainType<'a, Bv> + DomainType<'a, Cv> + DomainType<'a, Self>, 
[src]

impl<'a, Av, Bv, Cv, Dv, D> UnifyIn<'a, D> for (Val<Av>, Val<Bv>, Val<Cv>, Val<Dv>) where
    Av: UnifyIn<'a, D>,
    Bv: UnifyIn<'a, D>,
    Cv: UnifyIn<'a, D>,
    Dv: UnifyIn<'a, D>,
    D: DomainType<'a, Av> + DomainType<'a, Bv> + DomainType<'a, Cv> + DomainType<'a, Dv> + DomainType<'a, Self>, 
[src]

impl<'a, Av, Bv, Cv, Dv, Ev, D> UnifyIn<'a, D> for (Val<Av>, Val<Bv>, Val<Cv>, Val<Dv>, Val<Ev>) where
    Av: UnifyIn<'a, D>,
    Bv: UnifyIn<'a, D>,
    Cv: UnifyIn<'a, D>,
    Dv: UnifyIn<'a, D>,
    Ev: UnifyIn<'a, D>,
    D: DomainType<'a, Av> + DomainType<'a, Bv> + DomainType<'a, Cv> + DomainType<'a, Dv> + DomainType<'a, Ev> + DomainType<'a, Self>, 
[src]

Loading content...

Implementors

impl<'a, K, V, D> UnifyIn<'a, D> for LMap<K, V> where
    K: UnifyIn<'a, D> + Eq + Hash + Debug + 'a,
    V: UnifyIn<'a, D> + Debug + 'a,
    D: DomainType<'a, K> + DomainType<'a, V> + DomainType<'a, Self>, 
[src]

impl<'a, T, D> UnifyIn<'a, D> for LVec<T> where
    T: UnifyIn<'a, D>,
    D: DomainType<'a, T> + DomainType<'a, LVec<T>>, 
[src]

Loading content...