一応C++でもやってみましたが
http://twitter.com/zick_minoh/status/6223526156
2日近くも掛かってしまいました。ひーん。Haskell版をただ書き直しただけです。
templateとかtypenameとかすぐ忘れてしまいますね。なんでやねん的なのが多かったです。
あと結局あちこちにapplyを書く事になってしまったし、っていうか普通にBoostを使いましょう。Boostです!!
#include <typeinfo> #include <cxxabi.h> #include <iostream> char* demangle(const char *demangle) { int status; return abi::__cxa_demangle(demangle, 0, 0, &status); } struct True{typedef True type;}; struct False{typedef False type;}; struct BoolEq{ template<typename L,typename R> struct apply{}; }; template<> struct BoolEq::apply<True,True>{ typedef True type; }; template<> struct BoolEq::apply<False,False>{ typedef True type; }; template<> struct BoolEq::apply<True,False>{ typedef False type; }; template<> struct BoolEq::apply<False,True>{ typedef False type; }; template<typename Cond,typename Then,typename Else> struct IfThenElse{}; template<typename Then,typename Else> struct IfThenElse<True,Then,Else> { typedef typename Then::type type; }; template<typename Then,typename Else> struct IfThenElse<False,Then,Else> { typedef typename Else::type type; }; struct And { template<typename P,typename Q> struct apply{}; }; template<> struct And::apply<True,True>{typedef True type;}; template<> struct And::apply<True,False>{typedef False type;}; template<> struct And::apply<False,True>{typedef False type;}; template<> struct And::apply<False,False>{typedef False type;}; struct Or { template<typename P,typename Q> struct apply{}; }; template<> struct Or::apply<True,True>{typedef True type;}; template<> struct Or::apply<True,False>{typedef True type;}; template<> struct Or::apply<False,True>{typedef True type;}; template<> struct Or::apply<False,False>{typedef False type;}; struct Zero{typedef Zero type;}; template<typename V>struct Succ{ typedef Succ<typename V::type> type; }; typedef Succ<Zero> One; typedef Succ<One> Two; typedef Succ<Two> Three; typedef Succ<Three> Four; struct Add{ template<typename L,typename R> struct apply{}; }; template<> struct Add::apply<Zero,Zero>{ typedef Zero type; }; template<typename R> struct Add::apply<Zero,R>{ typedef typename R::type type; }; template<typename L,typename R> struct Add::apply<Succ<L>,R>{ typedef typename Succ<Add::template apply<L,R> >::type type; }; struct NatEq{ template<typename L,typename R> struct apply{}; }; template<> struct NatEq::apply<Zero,Zero>{ typedef True type; }; template<typename A> struct NatEq::apply<Succ<A>,Zero>{ typedef False type; }; template<typename B> struct NatEq::apply<Zero,Succ<B> >{ typedef False type; }; template<typename A,typename B> struct NatEq::apply<Succ<A>,Succ<B> >{ typedef typename NatEq::template apply<A,B>::type type; }; struct Less{ template<typename L,typename R> struct apply{}; }; template<> struct Less::apply<Zero,Zero>{ typedef False type; }; template<typename A> struct Less::apply<Succ<A>,Zero>{ typedef False type; }; template<typename B> struct Less::apply<Zero,Succ<B> >{ typedef True type; }; template<typename A,typename B> struct Less::apply<Succ<A>,Succ<B> >{ typedef typename Less::template apply<A,B>::type type; }; struct Nil{typedef Nil type;}; template<typename H,typename T> struct Cons{ typedef Cons<typename H::type,typename T::type> type; }; struct cons{ template<typename H,typename T> struct apply{ typedef typename Cons<H,T>::type type; }; }; struct Foldr{ template<typename Unary,typename Init,typename List> struct apply{ }; }; template<typename Binary,typename Init> struct Foldr::apply<Binary,Init,Nil>{ typedef Init type; }; template<typename Binary,typename Init,typename H,typename T> struct Foldr::apply<Binary,Init,Cons<H,T> >{ typedef typename Binary::template apply<H,typename Foldr::template apply<Binary,Init,T>::type>::type type; }; struct Append{ template<typename L,typename R> struct apply{ typedef typename Foldr::template apply<cons,R,L>::type type; }; }; struct Concat{ template<typename ListOfList> struct apply{ typedef typename Foldr::template apply<Append,Nil,ListOfList>::type type; }; }; struct Length{ template<typename List> struct apply{ //typedef typename Foldr::template apply<Lambda<_1,_2,Succ<_2> > >::type type; }; }; template<> struct Length::apply<Nil>{ typedef Zero type; }; template<typename H,typename T> struct Length::apply<Cons<H,T> >{ typedef typename Succ<typename Length::template apply<T>::type>::type type; }; template<typename Binary,typename Arg1> struct Partial{ struct Unary{ template<typename ARG2> struct apply{ typedef typename Binary::template apply<typename Arg1::type,typename ARG2::type>::type type; }; }; }; struct Filter{ template<typename Unary,typename List> struct apply{}; }; template<typename Unary> struct Filter::apply<Unary,Nil>{ typedef Nil type; }; template<typename Unary,typename H,typename T> struct Filter::apply<Unary,Cons<H,T> >{ typedef typename Unary::template apply<H>::type cond; typedef typename Filter::template apply<Unary,T>::type rest; typedef typename IfThenElse<cond,Cons<H,rest>,rest>::type type; }; struct Map{ template<typename Unary,typename List> struct apply{}; }; template<typename Unary> struct Map::apply<Unary,Nil>{ typedef Nil type; }; template<typename Unary,typename H,typename T> struct Map::apply<Unary,Cons<H,T> >{ typedef typename Unary::template apply<H>::type H_; typedef typename Map::template apply<Unary,T>::type T_; typedef Cons<H_,T_> type; }; struct Insert{ template<typename Elem,typename List> struct apply{ }; }; template<typename Elem> struct Insert::apply<Elem,Nil>{ typedef Cons<Cons<Elem,Nil>,Nil> type; }; template<typename Elem,typename H,typename T> struct Insert::apply<Elem,Cons<H,T> >{ typedef typename Cons<Elem,Cons<H,T> >::type A; typedef typename Insert::template apply<Elem,T>::type B; typedef typename Partial<cons,H>::Unary C; typedef typename Map::template apply<C,B>::type D; typedef typename Cons<A,D>::type type; }; struct Perm{ template<typename List> struct apply{}; }; template<> struct Perm::apply<Nil>{ typedef Cons<Nil,Nil> type; }; template<typename H,typename T> struct Perm::apply<Cons<H,T> >{ typedef typename Concat::template apply<typename Map::template apply<typename Partial<Insert,H>::Unary,typename Perm::template apply<T>::type>::type>::type type; }; template<typename A> struct Kotori{ typedef typename NatEq::template apply<typename A::type,One>::type type; }; template<typename A,typename B> struct Naru{ typedef typename Less::template apply<typename A::type,typename B::type>::type type; }; template<typename A> struct Suzu{ typedef typename NatEq::template apply<typename A::type,One>::type left; typedef typename NatEq::template apply<typename A::type,Two>::type right; typedef typename Or::template apply<left,right>::type type; }; template<typename A> struct Ayu{ typedef typename NatEq::template apply<typename A::type,One>::type left; typedef typename NatEq::template apply<typename A::type,Two>::type right; typedef typename Or::template apply<left,right>::type type; }; struct Kawaii{ template<typename List> struct apply{}; }; template<typename A,typename B,typename C,typename D> struct Kawaii::apply<Cons<A,Cons<B,Cons<C,Cons<D,Nil> > > > >{ typedef typename Kotori<A>::type kotori; typedef typename Naru<B,C>::type naru; typedef typename Suzu<C>::type suzu; typedef typename Ayu<D>::type ayu; typedef Cons<kotori,Cons<naru,Cons<suzu,Cons<ayu,Nil> > > > type; }; struct Judge{ template<typename List> struct apply{}; }; template<typename A,typename B,typename C,typename D> struct Judge::apply<Cons<A,Cons<B,Cons<C,Cons<D,Nil> > > > >{ typedef typename Kawaii::template apply<Cons<A,Cons<B,Cons<C,Cons<D,Nil> > > > >::type kawaii; typedef typename Filter::template apply<Partial<BoolEq,False>::Unary,kawaii>::type filterd; typedef typename Length::template apply<filterd>::type length; typedef typename NatEq::template apply<length,One>::type type; }; typedef Cons<One,Cons<Two,Cons<Three,Cons<Four,Nil> > > > RankSet; typedef Cons<One,Cons<Three,Cons<Four,Cons<Two,Nil> > > > Ans; typedef Perm::apply<RankSet>::type All; typedef Length::apply<All>::type Len; typedef Filter::apply<Judge,All>::type Compute; int main() { Compute compute; std::cout << demangle(typeid(compute).name()) << std::endl; } ==> ./a.out Cons<Cons<Succ<Zero>, Cons<Succ<Succ<Succ<Zero> > >, Cons<Succ<Succ<Succ<Succ<Zero> > > >, Cons<Succ<Succ<Zero> >, Nil> > > >, Nil>
「計算する」という目的に関してだけならば、GHCに比べて圧倒的に速い。
あと、型のレベルでの制約(Context)はHaskellだとType Classで付けられますが、C++だとConcept(は全然知らないのですが)がなんか使えないというかなんからしいので、なんかなんか・・・。
適当に作ったので、一貫性無く引数(的な所)で"::type"をしてますが適当なのでそれも適当です。
参考
デマングルに関しては
http://0xcc.net/blog/archives/000095.html
をそのまま使いました。