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