// // Copyright (c) 2000 Brian McNamara and Yannis Smaragdakis // // Permission to use, copy, modify, distribute and sell this software // and its documentation for any purpose is granted without fee, // provided that the above copyright notice and this permission notice // appear in all source code copies and supporting documentation. The // software is provided "as is" without any express or implied // warranty. #ifndef FCPP_PRELUDE_DOT_H #define FCPP_PRELUDE_DOT_H ////////////////////////////////////////////////////////////////////// // Note that this header file includes all the other FC++ header files, // so including this one (prelude.h) is sufficient to suck in the whole // library. ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // Here we define a bunch of functions from the Haskell Standard // Prelude (HSP). For documentation of their behaviors, see // http://haskell.org/onlinereport/standard-prelude.html // // A few of the functions are not from HSP, but seemed natural/useful. ////////////////////////////////////////////////////////////////////// #include "list.h" namespace fcpp { template class Compose0Helper { F f; G g; public: Compose0Helper( const F& a, const G& b ) : f(a), g(b) {} struct Sig : public FunType< typename F::Sig::ResultType > {}; typename F::Sig::ResultType operator()() const { return f( g() ); } }; struct Compose0 { template struct Sig : public FunType > {}; template Compose0Helper operator()( const F& f, const G& g ) const { return Compose0Helper( f, g ); } }; template class Compose1Helper { F f; G g; public: Compose1Helper( const F& a, const G& b ) : f(a), g(b) {} template struct Sig : public FunType< typename G::Sig::Arg1Type, typename F::Sig::ResultType>::ResultType > {}; template typename F::Sig::ResultType>::ResultType operator()( const T& x ) const { return f( g(x) ); } }; // Compose1 is Haskell's operator (.) for f.g where g is a one-arg struct Compose1 { template struct Sig : public FunType > {}; template Compose1Helper operator()( const F& f, const G& g ) const { return Compose1Helper( f, g ); } }; namespace { Compose1 compose1, compose; } template class Compose2Helper { F f; G g; H h; public: Compose2Helper( const F& a, const G& b, const H& c) : f(a), g(b), h(c) {} template struct Sig : public FunType< typename G::Sig::Arg1Type, typename F::Sig::ResultType, typename H::Sig::ResultType>::ResultType > {}; template typename F::Sig::ResultType, typename H::Sig::ResultType>::ResultType operator()( const T& x ) const { return f( g(x), h(x) ); } }; // Compose2 composes a two argument function with two one-argument // functions (taking the same type). This is quite useful for the // common case of binary operators struct Compose2 { template struct Sig : public FunType > {}; template Compose2Helper operator()(const F& f, const G& g, const H& h) const { return Compose2Helper( f, g, h ); } }; namespace { Compose2 _compose2; Curryable3 compose2(_compose2); } struct Until { template struct Sig : public FunType {}; template T operator()( const Pred& p, const Unary& op, const T& start ) const { if( p(start) ) return start; else return until( p, op, op(start) ); } }; namespace { Until _until; Curryable3 until(_until); } struct Last { template struct Sig : public FunType {}; template T operator()( const List& l ) const { if( null( tail( l ) ) ) return head(l); else return Last()(tail(l)); } }; namespace { Last last; } struct Init { template struct Sig : public FunType {}; template List operator()( const List& l ) const { if( null( tail( l ) ) ) return NIL; else return cons( head(l), curry( Init(), tail(l) ) ); } }; namespace { Init init; } struct Length { template struct Sig : public FunType {}; template size_t operator()( const List& l ) const { if( null(l) ) return 0; else return 1 + Length()( tail(l) ); } }; namespace { Length length; } // At is Haskell's operator (!!) struct At { template struct Sig : public FunType {}; template T operator()( const List& l, size_t n ) const { if( n==0 ) return head(l); else return At()( tail(l), n-1 ); } }; namespace { At _at; Curryable2 at(_at); } struct Filter { template struct Sig : public FunType {}; template List operator()( const P& p, const List& l ) const { if( null(l) ) return l; else if( p(head(l)) ) return cons( head(l), curry2( Filter(), p, tail(l) ) ); else return Filter()( p, tail(l) ); } }; namespace { Filter _filter; Curryable2 filter(_filter); } struct Concat { template struct Sig : public FunType {}; template List operator()( const List >& l ) const { if( null(l) ) return List(); else return cat( Const()(head(l)), curry(Concat(),(tail(l))) ); } }; namespace { Concat concat; } // Note: this isn't lazy, unless E and Op are. struct Foldr { template struct Sig : public FunType {}; template E operator()( const Op& op, const E& e, const List& l ) const { if( null(l) ) return e; else return op( head(l), Foldr()( op, e, tail(l) ) ); } }; namespace { Foldr _foldr; Curryable3 foldr(_foldr); } struct Foldr1 { template struct Sig : public FunType {}; template T operator()( const Op& op, const List& l ) const { return foldr( op, head(l), tail(l) ); } }; namespace { Foldr1 _foldr1; Curryable2 foldr1(_foldr1); } struct Foldl { template struct Sig : public FunType {}; template E operator()( const Op& op, const E& e, const List& l ) const { if( null(l) ) return e; else return Foldl()( op, op(e,head(l)), tail(l) ); } }; namespace { Foldl _foldl; Curryable3 foldl(_foldl); } struct Foldl1 { template struct Sig : public FunType {}; template T operator()( const Op& op, const List& l ) const { return foldl( op, head(l), tail(l) ); } }; namespace { Foldl1 _foldl1; Curryable2 foldl1(_foldl1); } struct Scanr { template struct Sig : public FunType > {}; template List operator()( const Op& op, const E& e, const List& l ) const { if( null(l) ) return cons( e, NIL ); else { List temp = Scanr()( op, e, tail(l) ); return cons( op( head(l), head(temp) ), temp ); } } }; namespace { Scanr _scanr; Curryable3 scanr(_scanr); } struct Scanr1 { template struct Sig : public FunType {}; template List operator()( const Op& op, const List& l ) const { if( null( tail(l) ) ) return l; else { List temp = Scanr1()( op, tail(l) ); return cons( op( head(l), head(temp) ), temp ); } } }; namespace { Scanr1 _scanr1; Curryable2 scanr1(_scanr1); } struct Scanl { template struct Sig : public FunType > {}; template List operator()( const Op& op, const E& e, const List& l ) const { if( null(l) ) return cons( e, NIL ); else return cons( e, curry3( Scanl(), op, op(e,head(l)), tail(l) ) ); } }; namespace { Scanl _scanl; Curryable3 scanl(_scanl); } struct Scanl1 { template struct Sig : public FunType {}; template List operator()( const Op& op, const List& l ) const { return scanl( op, head(l), tail(l) ); } }; namespace { Scanl1 _scanl1; Curryable2 scanl1(_scanl1); } struct Iterate { template struct Sig : public FunType > {}; template List operator()( const F& f, const T& x ) const { return cons( x, curry2( Iterate(), f, f(x) ) ); } }; namespace { Iterate _iterate; Curryable2 iterate(_iterate); } struct Repeat { template struct Sig : public FunType > {}; template List operator()( const T& x ) const { return cons( x, curry( Repeat(), x ) ); } }; namespace { Repeat repeat; } struct Map { template struct Sig : public FunType::ResultType> > {}; template typename Sig >::ResultType operator()( const F& f, const List& l ) const { if( null(l) ) return NIL; else return cons( f(head(l)), curry2( Map(), f, tail(l) ) ); } }; namespace { Map _map; Curryable2 map(_map); } struct Take { template struct Sig : public FunType {}; template List operator()( size_t n, const List& l ) const { if( n==0 || null(l) ) return NIL; else return cons( head(l), curry2( Take(), n-1, tail(l) ) ); } }; namespace { Take _take; Curryable2 take(_take); } struct Drop { template struct Sig : public FunType {}; template List operator()( size_t n, const List& l ) const { if( n==0 || null(l) ) return l; else return Drop()( n-1, tail(l) ); } }; namespace { Drop _drop; Curryable2 drop(_drop); } struct TakeWhile { template struct Sig : public FunType {}; template List operator()( const P& p, const List& l ) const { if( null(l) || !p( head(l) ) ) return NIL; else return cons( head(l), curry2( TakeWhile(), p, tail(l) ) ); } }; namespace { TakeWhile _takeWhile; Curryable2 takeWhile(_takeWhile); } struct DropWhile { template struct Sig : public FunType {}; template List operator()( const P& p, const List& l ) const { if( null(l) || !p( head(l) ) ) return l; else return DropWhile()( p, tail(l) ); } }; namespace { DropWhile _dropWhile; Curryable2 dropWhile(_dropWhile); } struct Replicate { template struct Sig : public FunType > {}; template List operator()( size_t n, const T& x ) const { return take( n, repeat(x) ); } }; namespace { Replicate _replicate; Curryable2 replicate(_replicate); } struct Cycle { template struct Sig : public FunType {}; template List operator()( const List& l ) const { return cat( Const()(l), curry( Cycle(), l ) ); } }; namespace { Cycle cycle; } struct SplitAt { template struct Sig : public FunType > {}; template std::pair,List > operator()( size_t n, const List& l ) const { if( n==0 || null(l) ) return std::make_pair( List(), l ); else { std::pair,List > temp = SplitAt()( n-1, tail(l) ); return std::make_pair( cons( head(l), temp.first ), temp.second ); } } }; namespace { SplitAt _splitAt; Curryable2 splitAt(_splitAt); } struct Span { template struct Sig : public FunType > {}; template std::pair,List > operator()( const P& p, const List& l ) const { if( null(l) || !p(head(l)) ) return std::make_pair( List(), l ); else { std::pair,List > temp = Span()( p, tail(l) ); return std::make_pair( cons(head(l),temp.first), temp.second ); } } }; namespace { Span _span; Curryable2 span(_span); } struct Break { template struct Sig : public FunType > {}; template std::pair,List > operator()( const P& p, const List& l ) const { return span( Compose1()( LogicalNot(), p ), l ); } }; namespace { Break _break_; Curryable2 break_(_break_); // C++ keyword, so add trailing underscore } template class FlipHelper { Binary op; public: FlipHelper( const Binary& b ) : op(b) {} template struct Sig : public FunType::ResultType > {}; template typename Binary::Sig::ResultType operator()( const Y& y, const X& x ) const { return op( x, y ); } }; struct Flip { template struct Sig : public FunType > {}; template FlipHelper operator()( const Binary& op ) const { return FlipHelper( op ); } }; namespace { Flip flip; } struct Reverse { template struct Sig : public FunType {}; template List operator()( const List& l ) const { return curry3( foldl, flip(cons), List(), l ); } }; namespace { Reverse reverse; } struct Or; struct And; struct All { template struct Sig : public FunType {}; template bool operator()( const P& p, const List& l ) const { return And()( map( p, l ) ); } }; namespace { All _all; Curryable2 all(_all); } struct Any { template struct Sig : public FunType {}; template bool operator()( const P& p, const List& l ) const { return Or()( map( p, l ) ); } }; namespace { Any _any; Curryable2 any(_any); } struct Elem { template struct Sig : public FunType {}; template bool operator()( const T& x, const List& l ) const { return any( bind2of2( Equal(), x ), l ); } }; namespace { Elem _elem; Curryable2 elem(_elem); } struct NotElem { template struct Sig : public FunType {}; template bool operator()( const T& x, const List& l ) const { return all( bind2of2( NotEqual(), x ), l ); } }; namespace { NotElem _notElem; Curryable2 notElem(_notElem); } struct Sum { template struct Sig : public FunType {}; template T operator()( const List& l ) const { return foldl( Plus(), 0, l ); } }; namespace { Sum sum; } struct Product { template struct Sig : public FunType {}; template T operator()( const List& l ) const { return foldl( Multiplies(), 0, l ); } }; namespace { Product product; } struct Minimum { template struct Sig : public FunType {}; template T operator()( const List& l ) const { return foldl1( Min(), l ); } }; namespace { Minimum minimum; } struct Maximum { template struct Sig : public FunType {}; template T operator()( const List& l ) const { return foldl1( Max(), l ); } }; namespace { Maximum maximum; } struct ZipWith { template struct Sig : public FunType >::ResultType> > {}; template List::ResultType> operator()( const Z& z, const List& a, const List& b) const { if( null(a) || null(b) ) return List::ResultType>(); else return cons( z(head(a),head(b)), curry3( ZipWith(), z, tail(a), tail(b) ) ); } }; namespace { ZipWith _zipWith; Curryable3 zipWith(_zipWith); } struct Zip { template struct Sig : public FunType > > {}; template List > operator()( const List& a, const List& b ) const { return zipWith( MakePair(), a, b ); } }; namespace { Zip _zip; Curryable2 zip(_zip); } struct Fst { template struct Sig : public FunType {}; template A operator()( const std::pair& p ) const { return p.first; } }; namespace { Fst fst; } struct Snd { template struct Sig : public FunType {}; template B operator()( const std::pair& p ) const { return p.second; } }; namespace { Snd snd; } struct Unzip { template struct Sig : public FunType, List > > {}; template typename Sig::ResultType operator()( const LPT& l ) const { typedef typename LPT::ElementType::first_type F; typedef typename LPT::ElementType::second_type S; return std::make_pair( List(curry2(map,fst,l)), List(curry2(map,snd,l)) ); } }; namespace { Unzip unzip; } struct GcdPrime { template struct Sig : public FunType {}; template T operator()( const T& x, const T& y ) const { if( y==0 ) return x; else return GcdPrime()( y, x%y ); } }; struct Gcd { template struct Sig : public FunType {}; template T operator()( const T& x, const T& y ) const { if( x==0 && y==0 ) throw "Gcd error: x and y both 0"; return GcdPrime()( x<0?-x:x, y<0?-y:y ); } }; namespace { Gcd _gcd; Curryable2 gcd(_gcd); } struct Odd { template struct Sig : public FunType {}; template bool operator()( const T& x ) const { return x%2==1; } }; namespace { Odd odd; } struct Even { template struct Sig : public FunType {}; template bool operator()( const T& x ) const { return x%2==0; } }; namespace { Even even; } ////////////////////////////////////////////////////////////////////// // Not HSP but close ////////////////////////////////////////////////////////////////////// // These next two are defined as _lazy_ versions of these operators on lists // We don't give them names because they conflict with C++ operators struct And : public CFunType,bool> { bool operator()( const List& l ) const { return null(dropWhile( curry2(Equal(),true), l )); } }; struct Or : public CFunType,bool> { bool operator()( const List& l ) const { return !null(dropWhile( curry2(Equal(),false), l )); } }; // FIX THIS: almost HSP, maybe templatize (rather than int) and/or use succ? struct EnumFrom : public CFunType > { List operator()( int x ) const { return listUntil( Never1(), Inc(), x ); } }; namespace { EnumFrom enumFrom; } // FIX THIS: almost HSP, maybe templatize (rather than int) and/or use succ? struct EnumFromTo : public CFunType > { List operator()( int x, int y ) const { return listUntil( bind2of2(Greater(),y), Inc(), x ); } }; namespace { EnumFromTo _enumFromTo; Curryable2 enumFromTo(_enumFromTo); } } // end namespace fcpp // FIX THIS: temporary kludge for backward compatibility with clients using namespace fcpp; #endif