Skip to content

Instantly share code, notes, and snippets.

@meki
Created March 28, 2015 11:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save meki/3435676657788e2ffbcf to your computer and use it in GitHub Desktop.
Save meki/3435676657788e2ffbcf to your computer and use it in GitHub Desktop.
C++ でカリー化関数を書いてみる(2変数限定) ref: http://qiita.com/_meki/items/742ce9788f03cee51070
#include <iostream>
#include <sstream>
#include <functional>
using namespace std;
/** カリー化 f(a, b) --> f(a)(b) */
template <typename A, typename B, typename C>
function < function < C(B) >(A) > curry(function<C(A, B)>& f)
{
return [&](A& a) -> function < C(B) > {
return [=](B& b) -> C {
return f(a, b);
};
};
}
/** アンカリー化 f(a)(b) --> f(a, b) */
template <typename A, typename B, typename C>
function< C(A, B) > uncurry(function < function < C(B) >(A) >& f)
{
return [&](A& a, B& b) -> C {
return f(a)(b);
};
}
int main(int argc, char* argv[])
{
// テスト用関数。 2つの文字列を連結する
function< string(string, string) > func = [](string a, string b) {
return a + b;
};
// 普通に使用
cout << func("Hello, ", "World!") << endl;
// カリー化して使用
auto func2 = curry(func);
cout << func2("Hello, ")("World!") << endl;
// カリー化されたものをさらにアンカリー化して使用
auto func3 = uncurry(func2);
cout << func3("Hello, ", "World!") << endl;
return 0;
}
/** カリー化 f(a, b) --> f(a)(b) */
def curry[A, B, C] (f: (A, B) => C) : A => (B => C) = {
(a : A) => ( (b : B) => f(a, b) )
}
/** アンカリー化 f(a)(b) --> f(a, b) */
def uncurry[A, B, C](f : A => (B => C) ) : (A, B) => C = {
(a : A, b : B) => f(a)(b)
}
/** A -> (B -> C) 型の関数オブジェクト */
template <typename A, typename B, typename C>
struct CurryImpl {
// コンストラクタでオリジナルの関数をキャプチャ
CurryImpl(function<C(A, B)>& f) : mFunc(f) {}
/** B -> C 型の関数オブジェクトをリターンする */
function< C(B) > operator () (A& a) {
return CurryImpl2(mFunc, a);
}
function<C(A, B)> mFunc;
/** B -> C 型の関数オブジェクト*/
struct CurryImpl2 {
// コンストラクタでオリジナル関数と第一引数をキャプチャ
CurryImpl2(function<C(A, B)>& f, A& a) : mFunc(f), mA(a) {}
C operator () (B& b) {
return mFunc(mA, b);
}
function<C(A, B)> mFunc;
A mA;
};
};
function< C(A, B) >
function < function < C(B) >(A)>
template <typename A, typename B, typename C>
function < function < C(B) >(A) > curry( function< C(A, B) >& f );
template <typename A, typename B, typename C>
std::function < std::function < C(B) >(A) > curry(std::function<C(A, B)>& f)
{
return [&](A& a) -> std::function < C(B) > {
return [=](B& b) -> C {
return f(a, b);
};
};
}
template <typename A, typename B, typename C>
std::function < std::function < C(B) >(A) > curry(std::function<C(A, B)>& f)
{
return [&](A& a) -> std::function < C(B) > {
return [&](B& b) -> C {
return f(a, b);
};
};
}
Hello, World!
Hello, World!
Hello, World!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment