diff options
Diffstat (limited to 'crates/elfmind/src/knowledge/traits.rs')
| -rw-r--r-- | crates/elfmind/src/knowledge/traits.rs | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/crates/elfmind/src/knowledge/traits.rs b/crates/elfmind/src/knowledge/traits.rs new file mode 100644 index 0000000..6db9250 --- /dev/null +++ b/crates/elfmind/src/knowledge/traits.rs @@ -0,0 +1,273 @@ +use crate::knowledge::*; + +pub trait DisplayNoun { + fn display_noun(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result; +} + +pub trait DisplayTuple { + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result; +} +impl<A: DisplayNoun> DisplayTuple for A { + // display any single noun as a 1-tuple + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + self.display_noun(f)?; + write!(f, ")") + } +} +impl<A: DisplayNoun, B: DisplayNoun> DisplayTuple for (A, B) { + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + self.0.display_noun(f)?; write!(f, ", ")?; + self.1.display_noun(f)?; + write!(f, ")") + } +} +impl<A: DisplayNoun, B: DisplayNoun, C: DisplayNoun> DisplayTuple for (A, B, C) { + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + self.0.display_noun(f)?; write!(f, ", ")?; + self.1.display_noun(f)?; write!(f, ", ")?; + self.2.display_noun(f)?; + write!(f, ")") + } +} +impl<A: DisplayNoun, B: DisplayNoun, C: DisplayNoun, D: DisplayNoun> DisplayTuple for (A, B, C, D) { + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + self.0.display_noun(f)?; write!(f, ", ")?; + self.1.display_noun(f)?; write!(f, ", ")?; + self.2.display_noun(f)?; write!(f, ", ")?; + self.3.display_noun(f)?; + write!(f, ")") + } +} +impl<A: DisplayNoun, B: DisplayNoun, C: DisplayNoun, D: DisplayNoun, E: DisplayNoun> DisplayTuple for (A, B, C, D, E) { + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + self.0.display_noun(f)?; write!(f, ", ")?; + self.1.display_noun(f)?; write!(f, ", ")?; + self.2.display_noun(f)?; write!(f, ", ")?; + self.3.display_noun(f)?; write!(f, ", ")?; + self.4.display_noun(f)?; + write!(f, ")") + } +} + +pub trait Concretizable { + type Concrete; + fn concretize(&self) -> Option<Self::Concrete>; +} +impl<A: Clone> Concretizable for Hole<A> { + type Concrete = A; + fn concretize(&self) -> Option<Self::Concrete> { + match self { + Self::Val(x) => Some(x.clone()), + _ => None, + } + } +} +impl< + A: Clone, + B: Clone, + > Concretizable for (Hole<A>, Hole<B>) { + type Concrete = (A, B); + fn concretize(&self) -> Option<Self::Concrete> { + let a = self.0.concretize()?; + let b = self.1.concretize()?; + Some((a, b)) + } +} +impl< + A: Clone, + B: Clone, + C: Clone, + > Concretizable for (Hole<A>, Hole<B>, Hole<C>) { + type Concrete = (A, B, C); + fn concretize(&self) -> Option<Self::Concrete> { + let a = self.0.concretize()?; + let b = self.1.concretize()?; + let c = self.2.concretize()?; + Some((a, b, c)) + } +} +impl< + A: Clone, + B: Clone, + C: Clone, + D: Clone, + > Concretizable for (Hole<A>, Hole<B>, Hole<C>, Hole<D>) { + type Concrete = (A, B, C, D); + fn concretize(&self) -> Option<Self::Concrete> { + let a = self.0.concretize()?; + let b = self.1.concretize()?; + let c = self.2.concretize()?; + let d = self.3.concretize()?; + Some((a, b, c, d)) + } +} +impl< + A: Clone, + B: Clone, + C: Clone, + D: Clone, + E: Clone, + > Concretizable for (Hole<A>, Hole<B>, Hole<C>, Hole<D>, Hole<E>) { + type Concrete = (A, B, C, D, E); + fn concretize(&self) -> Option<Self::Concrete> { + let a = self.0.concretize()?; + let b = self.1.concretize()?; + let c = self.2.concretize()?; + let d = self.3.concretize()?; + let e = self.4.concretize()?; + Some((a, b, c, d, e)) + } +} + +pub trait Substitutable { + fn substitute(&self, u: &Unification) -> Self; + fn map_variables<F>(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var; +} +impl<A: Clone + TryFrom<Noun>> Substitutable for Hole<A> { + fn substitute(&self, u: &Unification) -> Self { + match self { + x@Self::Var(v) => if let Some(y) = u.lookup(v) && let Ok(z) = A::try_from(y) { + Hole::Val(z) + } else { + x.clone() + } + x => x.clone(), + } + } + fn map_variables<F>(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var { + match self { + Self::Var(v) => Self::Var(f(*v)), + x => x.clone(), + } + } +} +impl< + A: Clone + TryFrom<Noun>, + B: Clone + TryFrom<Noun> + > Substitutable for (Hole<A>, Hole<B>) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b) = self; + (a.substitute(u), b.substitute(u)) + } + fn map_variables<F>(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var { + let (a, b) = self; + (a.map_variables(f), b.map_variables(f)) + } +} +impl< + A: Clone + TryFrom<Noun>, + B: Clone + TryFrom<Noun>, + C: Clone + TryFrom<Noun>, + > Substitutable for (Hole<A>, Hole<B>, Hole<C>) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b, c) = self; + (a.substitute(u), b.substitute(u), c.substitute(u)) + } + fn map_variables<F>(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var { + let (a, b, c) = self; + (a.map_variables(f), b.map_variables(f), c.map_variables(f)) + } +} +impl< + A: Clone + TryFrom<Noun>, + B: Clone + TryFrom<Noun>, + C: Clone + TryFrom<Noun>, + D: Clone + TryFrom<Noun>, + > Substitutable for (Hole<A>, Hole<B>, Hole<C>, Hole<D>) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b, c, d) = self; + (a.substitute(u), b.substitute(u), c.substitute(u), d.substitute(u)) + } + fn map_variables<F>(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var { + let (a, b, c, d) = self; + (a.map_variables(f), b.map_variables(f), c.map_variables(f), d.map_variables(f)) + } +} +impl< + A: Clone + TryFrom<Noun>, + B: Clone + TryFrom<Noun>, + C: Clone + TryFrom<Noun>, + D: Clone + TryFrom<Noun>, + E: Clone + TryFrom<Noun>, + > Substitutable for (Hole<A>, Hole<B>, Hole<C>, Hole<D>, Hole<E>) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b, c, d, e) = self; + (a.substitute(u), b.substitute(u), c.substitute(u), d.substitute(u), e.substitute(u)) + } + fn map_variables<F>(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var { + let (a, b, c, d, e) = self; + (a.map_variables(f), b.map_variables(f), c.map_variables(f), d.map_variables(f), e.map_variables(f)) + } +} + +pub trait Unifiable: Concretizable { + fn unify(&self, other: &Self::Concrete, u: Unification) -> Option<Unification>; +} +impl<A> Unifiable for Hole<A> where + Noun: From<A>, A: Copy, +{ + fn unify(&self, other: &Self::Concrete, mut u: Unification) -> Option<Unification> { + if u.unify_hole(self, other) { + Some(u) + } else { None } + } +} +impl<A, B> Unifiable for (Hole<A>, Hole<B>) where + Noun: From<A>, A: Copy, + Noun: From<B>, B: Copy, +{ + fn unify(&self, other: &Self::Concrete, mut u: Unification) -> Option<Unification> { + let (a1, b1) = self; + let (a2, b2) = other; + if u.unify_hole(a1, a2) && u.unify_hole(b1, b2) { + Some(u) + } else { None } + } +} +impl<A, B, C> Unifiable for (Hole<A>, Hole<B>, Hole<C>) where + Noun: From<A>, A: Copy, + Noun: From<B>, B: Copy, + Noun: From<C>, C: Copy, +{ + fn unify(&self, other: &Self::Concrete, mut u: Unification) -> Option<Unification> { + let (a1, b1, c1) = self; + let (a2, b2, c2) = other; + if u.unify_hole(a1, a2) && u.unify_hole(b1, b2) && u.unify_hole(c1, c2) { + Some(u) + } else { None } + } +} +impl<A, B, C, D> Unifiable for (Hole<A>, Hole<B>, Hole<C>, Hole<D>) where + Noun: From<A>, A: Copy, + Noun: From<B>, B: Copy, + Noun: From<C>, C: Copy, + Noun: From<D>, D: Copy, +{ + fn unify(&self, other: &Self::Concrete, mut u: Unification) -> Option<Unification> { + let (a1, b1, c1, d1) = self; + let (a2, b2, c2, d2) = other; + if u.unify_hole(a1, a2) && u.unify_hole(b1, b2) && u.unify_hole(c1, c2) && u.unify_hole(d1, d2) { + Some(u) + } else { None } + } +} +impl<A, B, C, D, E> Unifiable for (Hole<A>, Hole<B>, Hole<C>, Hole<D>, Hole<E>) where + Noun: From<A>, A: Copy, + Noun: From<B>, B: Copy, + Noun: From<C>, C: Copy, + Noun: From<D>, D: Copy, + Noun: From<E>, E: Copy, +{ + fn unify(&self, other: &Self::Concrete, mut u: Unification) -> Option<Unification> { + let (a1, b1, c1, d1, e1) = self; + let (a2, b2, c2, d2, e2) = other; + if u.unify_hole(a1, a2) && u.unify_hole(b1, b2) && u.unify_hole(c1, c2) && u.unify_hole(d1, d2) && u.unify_hole(e1, e2) { + Some(u) + } else { None } + } +} |
