#[macro_use]
extern crate maplit;
mod robinsons;
use std::fmt;
pub use robinsons::unify;
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
pub enum Term<T> {
Variable(T),
Constant(T),
Composite(T, Vec<Term<T>>),
}
impl fmt::Display for Term<String> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Term::Variable(ref name) => write!(f, "{}", name),
&Term::Constant(ref value) => write!(f, "{}", value),
&Term::Composite(ref name, ref terms) => {
let terms: Vec<String> = terms.iter().map(|t| format!("{}", t)).collect();
write!(f, "{}({})", name, terms.join(", "))
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_robinsons() {
let a = &Term::Constant("a");
assert_eq!(robinsons::unify(a, a), Some(hashmap!{}));
let b = &Term::Constant("b");
assert_eq!(robinsons::unify(a, b), None);
let _x = &Term::Variable("X");
assert_eq!(robinsons::unify(_x, _x), Some(hashmap!{}));
assert_eq!(robinsons::unify(a, _x), Some(hashmap!{_x => a}));
assert_eq!(robinsons::unify(_x, a), Some(hashmap!{_x => a}));
assert_eq!(robinsons::unify(a, _x), Some(hashmap!{_x => a}));
let _y = &Term::Variable("Y");
assert_eq!(robinsons::unify(_x, _y), Some(hashmap!{_x => _y}));
assert_eq!(robinsons::unify(_y, _x), Some(hashmap!{_y => _x}));
let f1 = &Term::Composite("f", vec![Term::Constant("a")]);
assert_eq!(robinsons::unify(f1, f1), Some(hashmap!{}));
let f2 = &Term::Composite("f", vec![Term::Constant("b")]);
assert_eq!(robinsons::unify(f1, f2), None);
let f3 = &Term::Composite("f", vec![Term::Variable("X")]);
assert_eq!(robinsons::unify(f1, f3), Some(hashmap!{_x => a}));
assert_eq!(robinsons::unify(f2, f3), Some(hashmap!{_x => b}));
let f4 = &Term::Composite("f", vec![Term::Variable("Y")]);
assert_eq!(robinsons::unify(f3, f4), Some(hashmap!{_x => _y}));
let g1 = &Term::Composite("g", vec![Term::Constant("a")]);
assert_eq!(robinsons::unify(f1, g1), None);
let g2 = &Term::Composite("g", vec![Term::Variable("X")]);
assert_eq!(robinsons::unify(f3, g2), None);
let g3 = &Term::Composite("g", vec![Term::Variable("Y")]);
assert_eq!(robinsons::unify(f3, g3), None);
let g4 = &Term::Composite("g", vec![Term::Variable("Y"), Term::Variable("Z")]);
assert_eq!(robinsons::unify(f3, g4), None);
let fg1 = &Term::Composite("f", vec![Term::Composite("g", vec![Term::Variable("X")])]);
assert_eq!(robinsons::unify(fg1, f4), Some(hashmap!{_y => g2}));
let fg2 = &Term::Composite(
"f",
vec![
Term::Composite("g", vec![Term::Variable("X")]),
Term::Variable("X"),
],
);
let f5 = &Term::Composite("f", vec![Term::Variable("Y"), Term::Constant("a")]);
assert_eq!(robinsons::unify(fg2, f5), Some(hashmap!{_x => a, _y => g2}));
assert_eq!(robinsons::unify(_x, f3), None);
}
}