#include #include "prelude.h" using namespace fcpp; using std::cout; using std::endl; /* A functoid to test the fixpoint operator. Implements the Fibonacci function. */ template struct FibGenHelper : public CFunType { X x; FibGenHelper (const X& in_x) : x(in_x) {} int operator () (const int& a) const { if (a == 0 || a == 1) return 1; else return x(a - 1) + x(a - 2); } }; struct FibGen { template struct Sig : public FunType > {}; template FibGenHelper operator () (const X& x) const { return FibGenHelper(x); } } fibgen; // An example of a polymorphic function, to show that Y isn't limited to // working on monomorphic functions. template struct MapGenHelper { Self self; MapGenHelper( const Self& s ) : self(s) {} template struct Sig : public FunType::ResultType> > {}; template typename Sig::ResultType operator()( const F& f, const L& l ) const { if( null(l) ) return NIL; else return cons( f(head(l)), curry2(self,f,tail(l)) ); } }; struct MapGen { template struct Sig : public FunType > {}; template MapGenHelper operator()( const Self& s ) const { return MapGenHelper(s); } } mapgen; template class YHelper { F function; public: YHelper(const F& f) : function(f) {} template struct Sig : public FunType >::ResultType,A>::ResultType> {}; template typename Sig::ResultType operator () (const A& a) const { return function(*this)(a); } }; struct Y { template struct Sig : public FunType > {}; template typename Sig::ResultType operator () (const F& f) const { return YHelper(f); } } y; // This is kinda shoddy. It is not too hard to make a single Y // combinator which can be applied to any functoid, regardless of the // number of arguments it expects. Here we just define two versions: // "y" which works for one-args and "y2" which works for two-args. If Y // is ever move into the library, I'll do it right; as an example file, // I don't care enough to bother. :) template class Y2Helper { F function; public: Y2Helper(const F& f) : function(f) {} template struct Sig : public FunType >::ResultType,A,B>::ResultType> {}; template typename Sig::ResultType operator()( const A& a, const B& b ) const { return function(*this)(a,b); } }; struct Y2 { template struct Sig : public FunType > {}; template typename Sig::ResultType operator () (const F& f) const { return Y2Helper(f); } } y2; int main () { cout << "Testing the Y combinator." << endl << "Should return a finonacci sequence, actually returned: "; for (int i = 0; i < 10; i++) cout << y(fibgen)(i) << " "; cout << endl << endl; cout << "Y test to show it works for polymorphic functions" << endl; cout << "Should return list of ints starting at 4..." << endl; List l = y2(mapgen)( fcpp::plus(3), enumFrom(1) ); l = take(10,l); while( !null(l) ) { cout << head(l) << " "; l = tail(l); } cout << endl; }