#include using namespace std; //----------------------------------------------------------------------- // 識別子 (変数名) //----------------------------------------------------------------------- typedef int id; //----------------------------------------------------------------------- // λ項の定義 // M ::= x | λx.M | M M //----------------------------------------------------------------------- template struct var; template struct abst; template struct appl; //----------------------------------------------------------------------- // そのλ項に出現しないFreshな変数名を取得 //----------------------------------------------------------------------- template struct newvar; template struct newvar< var > { static const int val = x+1; }; template struct newvar< abst > { static const int v1 = x+1; static const int v2 = newvar::val; static const int val = (v1 < v2 ? v2 : v1); }; template struct newvar< appl > { static const int v1 = newvar::val; static const int v2 = newvar::val; static const int val = (v1 < v2 ? v2 : v1); }; //----------------------------------------------------------------------- // 代入の定義 // [N/x]x = N // [N/x]y = y // [N/x]λx.M = M // [N/x]λy.M = λz.[N/x][z/y]M (z is not in N) // [N/x](M1 M2) = [N/x]M1 [N/x]M2 //----------------------------------------------------------------------- template struct substitute; template struct substitute< N, x, var > { typedef N term; }; template struct substitute< N, x, var > { typedef var term; }; template struct substitute< N, x, abst > { typedef abst term; }; template struct substitute< N, x, abst > { static const int z = newvar< appl >::val; typedef abst,y,M>::term >::term > term; }; template struct substitute< N, x, appl > { typedef appl< typename substitute::term, typename substitute::term > term; }; //----------------------------------------------------------------------- // β-reduction // β(x) -> x // β(λx.M) -> λx.β(M) // β(x M2) -> x β(M2) // β(λx.M1 M2) -> β([M2/x] M1) // β(M1 M2) -> β(β(M1) M2) if M1 !=β(M1) // β(M1 M2) -> M1 β(M2) otherwise //----------------------------------------------------------------------- template struct reduct; template struct reduct< var > { typedef var term; }; template struct reduct< abst > { typedef abst< x, typename reduct::term > term; }; template struct reduct< appl,M2> > { typedef appl< var, typename reduct::term > term; }; template struct reduct< appl,M2> > { typedef typename reduct< typename substitute::term >::term term; }; // helper begin template struct is_ { enum{same=false}; }; template struct is_ { enum{same=true}; }; template struct red_helper { typedef appl::term> term; }; template struct red_helper { typedef typename reduct< appl >::term term; }; // helper_end template struct reduct< appl > { typedef typename reduct::term rM1; typedef typename red_helper< is_::same, M1, rM1, M2 >::term term; }; //----------------------------------------------------------------------- // できるだけ小さいidになるように変数名のつけかえ (Debug用) //----------------------------------------------------------------------- template struct shorterid; template struct shorterid< base, var > { typedef var term; }; template struct shorterid< base, abst > { typedef abst::term> term; }; template struct shorterid< base, appl > { typedef appl::term, typename shorterid::term> term; }; //----------------------------------------------------------------------- // 出力 (Debug用) //----------------------------------------------------------------------- template struct print_impl; template struct print { static ostream& to( ostream& os ) { print_impl< typename shorterid::val-1, M>::term >::to( os ); return os; }; }; template struct print_impl< var > { static void to( ostream& os ) { if( x == 0 ) os << 'a'; else for(int xx=x; xx>0; xx/=26) os << char('a' + (xx % 26)); } }; template struct print_impl< abst > { static void to( ostream& os ) { os << 'L'; print_impl< var >::to( os ); os << '.'; print_impl< M >::to( os ); } }; template struct print_impl< appl > { static void to( ostream& os ) { os << '('; print_impl::to( os ); os << ' '; print_impl::to( os ); os << ')'; } }; //----------------------------------------------------------------------- // test //----------------------------------------------------------------------- int main() { #define DO_PRINT print< reduct< #define END_PRINT >::term >::to(cout) << endl; enum{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}; typedef abst > > zero; typedef abst,var > > > one; typedef abst, appl,var > > > > two; typedef abst, appl, appl,var > > > > > three; typedef abst, appl, appl, appl,var > > > > > > four; // 足し算 typedef abst,var >, appl< appl,var >,var > > > > > > add; // 掛け算 typedef abst, appl< var,var > > > > > mult; // 1引く typedef abst, abst, appl,var > > > > >, abst< d, var > >, abst< i,var > > > > > pred; // 引き算 typedef abst, pred >, var > > > sub; DO_PRINT appl, two> END_PRINT DO_PRINT appl, two> END_PRINT }