use term::{Term, Error, abs, app};
use term::Term::*;
use term::Error::*;
use church::booleans::{tru, fls};
pub fn pair() -> Term {
abs!(3, app!(Var(1), Var(3), Var(2)))
}
pub fn fst() -> Term { abs(app(Var(1), tru())) }
pub fn snd() -> Term { abs(app(Var(1), fls())) }
pub fn uncurry() -> Term {
abs!(2, app!(
Var(2),
app(Var(1), tru()),
app(Var(1), fls())
))
}
impl Term {
pub fn is_pair(&self) -> bool {
self.unpair_ref().is_ok()
}
pub fn unpair(self) -> Result<(Term, Term), Error> {
let candidate = if let Abs(abstracted) = self { *abstracted } else { self };
if let Ok((wrapped_a, b)) = candidate.unapp() {
Ok((wrapped_a.rhs()?, b))
} else {
Err(NotAPair)
}
}
pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
let candidate = if let Abs(ref abstracted) = *self { abstracted } else { self };
if let Ok((wrapped_a, b)) = candidate.unapp_ref() {
Ok((wrapped_a.rhs_ref()?, b))
} else {
Err(NotAPair)
}
}
pub fn unpair_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
let candidate = if let Abs(ref mut abstracted) = *self { abstracted } else { self };
if let Ok((wrapped_a, b)) = candidate.unapp_mut() {
Ok((wrapped_a.rhs_mut()?, b))
} else {
Err(NotAPair)
}
}
pub fn fst(self) -> Result<Term, Error> {
Ok(self.unpair()?.0)
}
pub fn fst_ref(&self) -> Result<&Term, Error> {
Ok(self.unpair_ref()?.0)
}
pub fn fst_mut(&mut self) -> Result<&mut Term, Error> {
Ok(self.unpair_mut()?.0)
}
pub fn snd(self) -> Result<Term, Error> {
Ok(self.unpair()?.1)
}
pub fn snd_ref(&self) -> Result<&Term, Error> {
Ok(self.unpair_ref()?.1)
}
pub fn snd_mut(&mut self) -> Result<&mut Term, Error> {
Ok(self.unpair_mut()?.1)
}
}
impl From<(Term, Term)> for Term {
fn from((t1, t2): (Term, Term)) -> Self {
abs(app!(Var(1), t1, t2))
}
}