#include #include #define FCPP_ENABLE_LAMBDA #include "prelude.h" using namespace fcpp; using std::cout; using std::endl; ////////////////////////////////////////////////////////////////////// // Here I do the ST monad as per the "State in Haskell" paper struct MutVar { int name; MutVar(int n):name(n) {} bool operator<( const MutVar& m ) const { return name < m.name; } }; struct STM { // FIX THIS // for simplicity for now, let's fix types so that the type of // references is always just MutVar and the type of thing they // reference is always just int typedef std::map State; struct XUnit { template struct Sig : public FunType::ResultType> {}; template typename Sig::ResultType operator()( const A& a ) const { return makePair(a); } }; typedef Full1 Unit; static Unit unit; struct XBind { template struct Sig : public FunType,LET > >, CALL > >, CALL > > > > >::Type > {}; template typename Sig::ResultType operator()( const M& m, const K& k ) const { LambdaVar<1> P; LambdaVar<2> s0; return lambda(s0)[ let[ P == m[s0] ].in[ k[fst[P]][snd[P]] ] ]; } }; typedef Full2 Bind; static Bind bind; // FIX THIS am currently copying the state; eventually the whole point // is not to, duh struct XNewVarHelper : public CFunType > { std::pair operator()( State s, int a ) const { // find the first available name int i = 0; while( s.find( MutVar(i) ) != s.end() ) ++i; // update the state, return the reference s.insert( makePair(MutVar(i),a) ); return makePair(MutVar(i),s); } }; typedef Full2 NewVarHelper; struct XNewVar { template struct Sig : public FunType,CALL,int> > >::Type> {}; Sig::ResultType operator()( const int& a ) const { LambdaVar<1> S; return lambda(S)[ NewVarHelper()[S,a] ]; } }; typedef Full1 NewVar; static NewVar newVar; // ditto struct XWriteVarHelper : public CFunType > { std::pair operator()( State s, MutVar v, int a ) const { s.find(v.name)->second = a; return makePair(empty,s); } }; typedef Full3 WriteVarHelper; struct XWriteVar { template struct Sig : public FunType,CALL,MutVar,int> > >::Type > {}; Sig::ResultType operator()( const MutVar& v, const int& a ) const { LambdaVar<1> S; return lambda(S)[ WriteVarHelper()[S,v,a] ]; } }; typedef Full2 WriteVar; static WriteVar writeVar; // ditto struct XReadVarHelper : public CFunType > { std::pair operator()( const State& s, MutVar v ) const { int r = s.find(v.name)->second; return makePair(r,s); } }; typedef Full2 ReadVarHelper; struct XReadVar { template struct Sig : public FunType,CALL,MutVar> > >::Type > {}; Sig::ResultType operator()( const MutVar& v ) const { LambdaVar<1> S; return lambda(S)[ ReadVarHelper()[S,v] ]; } }; typedef Full1 ReadVar; static ReadVar readVar; struct XRun { template struct Sig : public FunType {}; template int operator()( const ST& st ) const { State s; // initial empty state (eventually could be new-ed) std::pair p = st(s); int r = p.first; // eventually could delete here return r; } }; typedef Full1 Run; static Run run; }; STM::Unit STM::unit; STM::Bind STM::bind; STM::NewVar STM::newVar; STM::ReadVar STM::readVar; STM::WriteVar STM::writeVar; STM::Run STM::run; ////////////////////////////////////////////////////////////////////// LEType,BIND<2,int>, CALL,LV<2> > > > >::Type foo() { LambdaVar<1> X; LambdaVar<2> Y; return lambda()[ let[ X == 4, Y == 1 ].in[ minus[X,Y] ] ]; } LEType >,GETS<2,List >, CALL::Type,CALL,LV<2> > > > > >::Type bar() { LambdaVar<1> X; LambdaVar<2> Y; return lambda()[ doM[ X <= list_with(1,2), Y <= list_with(3,4), unitM()[ makePair[X,Y] ] ] ]; } LEType,IF0,int>,int,int> > > >::Type baz() { LambdaVar<1> X; return lambda()[ let[ X == 3 ].in[ if0[less[X,10],1,0] ] ]; } LEType,LV<2> >,GETS<1,List >, GUARD,GETS<2,List >,GUARD,LV<1> >, int> > > > >::Type qux() { LambdaVar<1> X; LambdaVar<2> Y; return lambda()[ compM()[ makePair[X,Y] | X<=list_with(1,2), guard[true], Y<=list_with(3,4), guard[equal[divides[Y,X],3] ] ] ]; } template std::ostream& operator<<( std::ostream& o, const Maybe& mx ) { if( mx.is_nothing() ) o << "Nothing"; else o << "Just " << mx.value(); return o; } int main() { LambdaVar<1> X; LambdaVar<2> Y; LambdaVar<3> L; LambdaVar<4> V; // comp()[ makePair[X,Y] | X <= list_with(1,2), // Y <= list_with(3,4) ] //==> // bind[list_with(1,2), lambda(X)[ // comp()[ makePair[X,Y] | Y <= list_with(3,4) ] ] //==> // bind[list_with(1,2), lambda(X)[ // bind[list_with(3,4), lambda(Y)[ unit()[ makePair[X,Y] ] // ] ] ] ] // g++ won't define the static members without this (void) &(StateM::unit); (void) &(StateM::bind); List > l = list_with(1,2) ^bind^ lambda(X)[ list_with(3,4) %bind% lambda(Y)[ unitM()[ makePair[X,Y] ] ] ]; while( !null(l) ) { cout << head(l).first << "," << head(l).second << endl; l = tail(l); } cout << "---------" << endl; std::pair p = bindM()(1, lambda(X)[ bindM()[2, lambda(Y)[ unitM()[ makePair[X,Y] ] ] ] ] ); cout << p.first << "," << p.second << endl; cout << "---------" << endl; p = bindM >()( lambda(X)[ makePair[3,X] ], lambda(Y)[ unitM >()[ Y ] ])(0); cout << p.first << "," << p.second << endl; p = bindM_ >()( StateM::assign(3), bindM >()( StateM::fetch(), lambda(X)[ unitM >()[ X ] ] ) )(0); cout << p.first << "," << p.second << endl; cout << "---------" << endl; /* FIX THIS (just a comment window) */ cout << foo()() << endl; cout << "---------" << endl; l = lambda()[ doM[ X <= list_with(1,2), Y <= list_with(3,4), unitM()[ makePair[X,Y] ] ] ](); while( !null(l) ) { cout << head(l).first << "," << head(l).second << endl; l = tail(l); } cout << "---------" << endl; l = bar()(); while( !null(l) ) { cout << head(l).first << "," << head(l).second << endl; l = tail(l); } cout << "---------" << endl; l = joinM()( mapM()( lambda(X)[ mapM()[ lambda(Y)[ makePair[X,Y] ], list_with(3,4) ] ], list_with(1,2) ) ); while( !null(l) ) { cout << head(l).first << "," << head(l).second << endl; l = tail(l); } cout << "---------" << endl; l = lambda()[ compM()[ makePair[X,Y] | X<=list_with(1,2), Y<=list_with(3,4) ] ](); while( !null(l) ) { cout << head(l).first << "," << head(l).second << endl; l = tail(l); } cout << "---------" << endl; p = lambda()[ compM()[ makePair[X,Y] | X <= 1, Y <= 1 ] ](); cout << p.first << "," << p.second << endl; cout << "---------" << endl; p = lambda(X)[ compM()[ makePair[X,Y] | Y <= 1 ] ](1); cout << p.first << "," << p.second << endl; cout << "---------" << endl; List li = lambda(L)[ map[ lambda(X)[ plus[head[L],X] ], L ] ]( list_with(2,3,4) ); cout << at(li,0) << " " << at(li,1) << " " << at(li,2) << endl; cout << "---------" << endl; cout << baz()() << endl; cout << "---------" << endl; l = lambda()[ compM()[ makePair[X,Y] | X<=list_with(1,2), Y<=list_with(3,4), guard[greater[X,Y]] ] ](); cout << length(l) << endl; l = lambda()[ compM()[ makePair[X,Y] | X<=list_with(1,2), guard[greater[X,3]], Y<=list_with(3,4) ] ](); cout << length(l) << endl; cout << "---------" << endl; l = lambda()[ compM()[ makePair[X,Y] | X<=list_with(1,2), guard[true], Y<=list_with(3,4), guard[equal[divides[Y,X],3] ] ] ](); while( !null(l) ) { cout << head(l).first << "," << head(l).second << endl; l = tail(l); } cout << "---------" << endl; l = qux()(); while( !null(l) ) { cout << head(l).first << "," << head(l).second << endl; l = tail(l); } cout << "---------" << endl; Maybe mx = NOTHING; Maybe my = just(3); mx = lambda()[ compM()[ plus[X,Y] | X<=mx, Y<=my ] ](); cout << mx << endl; cout << "---------" << endl; mx = just(2); my = just(3); mx = lambda()[ compM()[ plus[X,Y] | X<=mx, Y<=my ] ](); cout << mx << endl; cout << "---------" << endl; mx = just(2); my = just(3); mx = lambda()[ compM()[ plus[X,Y] | X<=mx, Y<=my, guard[false] ] ](); cout << mx << endl; cout << "---------" << endl; mx = lambda()[ doM[ X<=just[2], Y<=just[4], unitM()[plus[X,Y]] ] ](); cout << mx << endl; cout << "-----------------------" << endl; cout << STM::run( lambda()[ compM()[ X | V <= STM::newVar[3], STM::writeVar[V,4], X <= STM::readVar[V] ] ]() ) << endl; cout << "---------" << endl; }