C++でモナド
檜山先生のモナドの説明を純粋関数型言語C++で書いてみました。
#include "stdafx.h" template<int n> struct int_{static const int value=n;}; //例の最初に出てくる副作用ありバージョンはそもそも記述できないのでいきなり副作用なしバージョン。 template<typename T,typename C> struct Countup; template<typename T,int countup> struct Countup<T,int_<countup>> {}; template<typename x,typename y> struct sum_countup5_ex; template<int x,int xc,int y,int yc> struct sum_countup5_ex<Countup<int_<x>,int_<xc>>,Countup<int_<y>,int_<yc>>> { typedef Countup<int_<x+y>,int_<xc+yc+5>> result; }; template<typename t> struct noeffect { typedef Countup<t,int_<0>> result; }; //テンプレートは文字列を扱えないのでちょっとずるをする #define sizeof_v(v) (sizeof(v) / sizeof(v[0])) #define sizeof_s(s) (sizeof_v(s) - 1) //\0のぶん template<int n> struct length_countup { typedef Countup<int_<n>,int_<n>> result; }; template<typename t> struct countup_ex; template<int r,int c> struct countup_ex<Countup<int_<r>,int_<c>>> { typedef Countup<void,int_<r+c>> result; }; //カウントアップされる本体 int count=0; template<typename T> struct CountupMain; template<int value,int countup> struct CountupMain<Countup<int_<value>,int_<countup>>> { static int exec() { count+=countup; return value; } }; template<int countup> struct CountupMain<Countup<void,int_<countup>>> { static const char* exec() { count+=countup; return "(no result)"; } }; #include <iostream> using std::cout; using std::endl; int _tmain(int argc, _TCHAR* argv[]) { cout << "count == " << count << endl; cout << "length_countup(\"Hello, world!\") == " << CountupMain<length_countup<sizeof_s("Hello, world!")>::result>::exec() << endl; cout << "count == " << count << endl; cout << "noeffect(1) == " << CountupMain<noeffect<int_<1>>::result>::exec() << endl; cout << "count == " << count << endl; cout << "sum_countup5_ex(noeffect(1),length_countup(\"Hello, world!\")) == " << CountupMain<sum_countup5_ex<noeffect<int_<1>>::result, length_countup<sizeof_s("Hello, world!")>::result >::result>::exec() << endl; cout << "count == " << count << endl; cout << "countup_ex(sum_countup5_ex(noeffect(1),length_countup(\"Hello, world!\")) == " << CountupMain<countup_ex<sum_countup5_ex< noeffect<int_<1>>::result, length_countup<sizeof_s("Hello, world!")>::result >::result>::result>::exec() << endl; cout << "count == " << count << endl; }
副作用がみごとにCoutupMain<>::exec()の中にまとめられてしまいました。
count == 0 length_countup("Hello, world!") == 13 count == 13 noeffect(1) == 1 count == 13 sum_countup5_ex(noeffect(1),length_countup("Hello, world!")) == 14 count == 31 countup_ex(sum_countup5_ex(noeffect(1),length_countup("Hello, world!")) == (no r esult) count == 63