νλ‘κ·Έλλ¨Έλ₯Ό μν λ²μ£Όλ‘ μ μ΄μ λͺ κ°μ κΈμμ ν¬κ³ μμ λ²μ£Όμ λͺ κ°μ§ μμλ₯Ό μ μνμ΅λλ€. μ΄ κΈμμλ λ κ³ κΈ μμλ₯Ό ν΅ν΄ μ€λͺ μ μ§νν κ²μ λλ€. μ΄ μ리μ¦λ₯Ό μ²μ μ νλ κ²½μ° λͺ©μ°¨λ₯Ό νμΈνμΈμ.
νμ κ³Ό μμ ν¨μλ₯Ό λ²μ£Όλ‘ λͺ¨λΈλ§ νλ λ°©λ²μ μ΄ν΄λ³΄μμ΅λλ€. λν λ²μ£Όλ‘ μμ λΆμμ©, μ¦ μμνμ§ μμ ν¨μλ₯Ό λͺ¨λΈλ§νλ λ°©λ²μ΄ μλ€κ³ μΈκΈνμ΅λλ€. μ€νμ κΈ°λ‘νκ±°λ μΆμ νλ ν¨μλΌλ μμλ₯Ό μ΄ν΄λ³΄κ² μ΅λλ€. λͺ λ Ήν μΈμ΄μμλ μλμ κ°μ΄ μ μ μνλ₯Ό λ³κ²½νμ¬ κ΅¬νλ κ°λ₯μ±μ΄ μμ΅λλ€.
string logger;
bool negate(bool b) {
logger += "Not so! ";
return !b;
}
μ΄ κΈ°μ΅λ λ²μ μ ν¨μλ λ‘κ·Έλ₯Ό μμ±νμ§ λͺ»νκΈ° λλ¬Έμ μμ ν¨μκ° μλλΌλ κ²μ μκ³ μμ΅λλ€. μ΄ ν¨μμλ λΆμμ©κ° μμ΅λλ€.
νλ νλ‘κ·Έλλ°μμ μ°λ¦¬λ κ°λ₯ν ν λ³κ²½ κ°λ₯ν μ μ μνλ₯Ό νΌνλ €κ³ λ Έλ ₯ν©λλ€. λμμ±μ 볡μ‘μ± λλ¬Έμ λλ€. κ·Έλ¦¬κ³ λΌμ΄λΈλ¬λ¦¬μ μ΄λ° μ½λλ₯Ό λ£μ§ μμ κ²μ λλ€.
λ€ννλ μ΄ ν¨μλ₯Ό μμνκ² λ§λλ κ²μ΄ κ°λ₯ν©λλ€. λ‘κ·Έλ₯Ό λͺ μμ μΌλ‘ μνμΌλ‘ μ λ¬νκΈ°λ§ νλ©΄ λ©λλ€. λ¬Έμμ΄ μΈμλ₯Ό μΆκ°νκ³ μ λ°μ΄νΈλ λ‘κ·Έκ° ν¬ν¨λ λ¬Έμμ΄κ³Ό μΌλ° μΆλ ₯μ μμΌλ‘ λ§λ€μ΄ λ³΄κ² μ΅λλ€.
pair<bool, string> negate(bool b, string logger) {
return make_pair(!b, logger + "Not so! ");
}
μ΄ ν¨μλ μμνκ³ λΆμμ©μ΄ μμΌλ©° λμΌν μΈμλ‘ νΈμΆλ λλ§λ€ λμΌν μμ λ°ννλ©° νμν κ²½μ° κΈ°μ΅ν μ μμ΅λλ€. κ·Έλ¬λ λ‘κ·Έμ λμ λλ νΉμ±μ κ³ λ €ν λ μ£Όμ΄μ§ νΈμΆλ‘ μ΄μ΄μ§ μ μλ λͺ¨λ κ°λ₯ν λ‘κ·Έλ€μ κΈ°μ΅ν΄μΌ ν©λλ€. μλμ κ°κ° κΈ°μ΅λλ νλͺ©μ΄ μμ΅λλ€.
negate(true, "It was the best of times. ");
// λλ
negate(true, "It was the worst of times. ");
// λ±λ±
λν λΌμ΄λΈλ¬λ¦¬ κΈ°λ₯μ μν μμ£Ό μ’μ μΈν°νμ΄μ€λ μλλλ€. νΈμΆμλ λ°ν νμ μ λ¬Έμμ΄μ μμ λ‘κ² λ¬΄μν μ μμΌλ―λ‘ ν° λΆλ΄μ μλλλ€. κ·Έλ¬λ μ λ ₯μΌλ‘ λ¬Έμμ΄μ μ λ¬ν΄μΌ νλ―λ‘ λΆνΈν μ μμ΅λλ€.
κ°μ μΌμ λ λ°©ν΄κ° λλ λ°©λ²μΌλ‘ κ΄μ¬μ¬λ₯Ό λΆλ¦¬νλ λ°©λ²μ΄ μμκΉμ? μ΄ κ°λ¨ν μμμμ negate ν¨μμ λͺ©μ μ νλμ Boolenaμ λ€λ₯Έ κ²μΌλ‘ λ°κΎΈλ κ²μ λλ€. λ‘κ·Έλ₯Ό λ¨κΈ°λ κ²μ 2μ°¨μ μ λλ€. λ¬Όλ‘ κΈ°λ‘λλ λ©μμ§λ ν¨μμ λ°λΌ λ€λ₯΄μ§λ§ λ©μμ§λ₯Ό νλμ μ°μ λ‘κ·Έλ‘ μ§κ³νλ μμ μ λ³κ°μ λ¬Έμ μ λλ€. μ°λ¦¬λ μ¬μ ν ν¨μκ° λ¬Έμμ΄μ μμ±νκΈ°λ₯Ό μνμ§λ§, λ‘κ·Έ μμ±μμ λΆλ΄μ λμ΄μ£Όκ³ μΆμ΅λλ€. ννν μ μλ ν΄κ²°μ± μ μλμ κ°μ΅λλ€.
pair<bool, string> negate(bool b) {
return make_pair(!b, "Not so! ");
}
μ΄ μμ΄λμ΄λ λ‘κ·Έκ° ν¨μ νΈμΆ κ°μ μμ§λλ€λ κ²μ λλ€.
μ΄κ²μ΄ μ΄λ»κ² κ°λ₯νμ§ λ³΄κΈ° μν΄ μ‘°κΈ λ νμ€μ μΈ μμλ‘ λ°κΎΈμ΄ λ³΄κ² μ΅λλ€. λ¬Έμμ΄μμ μλ¬Έμλ₯Ό λλ¬Έμλ‘ λ°κΎΈλ νλμ ν¨μκ° μμ΅λλ€.
string toUpper(string s) {
string result;
int (*toupperp)(int) = &toupper; // toupperλ overload λμμ΅λλ€.
transform(begin(s), end(s), back_inserter(result), toupperp);
return result;
}
λ€λ₯Έ νλλ λ¬Έμμ΄μ 곡백 κ²½κ³λ‘ λ¬Έμμ΄ λ²‘ν°λ‘ λλλλ€.
vector<string> toWords(string s) {
return words(s);
}
μ€μ μμ μ 보쑰 ν¨μ wordsμμ μνλ©λλ€.
vector<string> words(string s) {
vector<string> result{""};
for (auto i = begin(s); i != end(s); ++i)
{
if (isspace(*i))
result.push_back("");
else
result.back() += *i;
}
return result;
}
toUpper
λ° toWords
ν¨μλ₯Ό μμ ν΄ μΌλ° λ°ν κ° μμ λ©μμ§ λ¬Έμμ΄μ νΌκΈ°λ°±(piggyback) νλλ‘ ν©λλ€.
μ°λ¦¬λ μ΄λ° ν¨μμ λ°ν κ°μ "μ₯μ"(embellish)ν κ²μ
λλ€. 첫 λ²μ§Έ μ»΄ν¬λνΈκ° μμ νμ
Aμ κ°μ΄κ³ λ λ²μ§Έ κ΅¬μ± μμκ° λ¬Έμμ΄μΈ μμ μΊ‘μννλ ν
νλ¦Ώ Writer
λ₯Ό μ μν΄ μΌλ°μ μΈ λ°©μμΌλ‘ μ²λ¦¬ν΄ λ³΄κ² μ΅λλ€.
template<class A>
using Writer = pair<A, string>;
μλλ μ₯μλ ν¨μμ λλ€.
Writer<string> toUpper(string s) {
string result;
int (*toupperp)(int) = &toupper;
transform(begin(s), end(s), back_inserter(result), toupperp);
return make_pair(result, "toUpper ");
}
Writer<vector<string>> toWords(string s) {
return make_pair(words(s), "toWords ");
}
μ΄ λ ν¨μλ₯Ό λ¬Έμμ΄μ λλ¬Έμλ‘ λ°κΎΈκ³ μ΄λ₯Ό λ¨μ΄λ‘ λλλ λ λ€λ₯Έ μ₯μλ ν¨μλ‘ ν©μ±νκ³ κ·Έ μμ μ λ‘κ·Έλ₯Ό μμ±νκΈ°λ₯Ό μν©λλ€. λ°©λ²μ μλμ κ°μ΅λλ€.
Writer<vector<string>> process(string s) {
auto p1 = toUpper(s);
auto p2 = toWords(p1.first);
return make_pair(p2.first, p1.second + p2.second);
}
μ°λ¦¬λ λͺ©νλ₯Ό λ¬μ±νμ΅λλ€. λ‘κ·Έ μμ§μ λ μ΄μ κ°λ³ ν¨μμ λ¬Έμ κ° μλλλ€. μ΄κ²λ€μ μ체μ μΈ λ©μμ§λ₯Ό μμ±ν λ€μ μΈλΆμμ λ ν° λ‘κ·Έλ‘ μ°κ²°ν©λλ€.
μ΄μ μ΄ μ€νμΌλ‘ μμ±λ μ 체 νλ‘κ·Έλ¨μ μμν΄ λ³΄μΈμ. λ°λ³΅μ μ΄κ³ μ€λ₯κ° λ°μνκΈ° μ¬μ΄ μ½λμ μ λͺ½μ λλ€. νμ§λ§ μ°λ¦¬λ νλ‘κ·Έλλ¨Έμ λλ€. μ°λ¦¬λ λ°λ³΅μ μΈ μ½λλ₯Ό μ²λ¦¬νλ λ°©λ²μ μκ³ μμ΅λλ€. μ°λ¦¬λ μ΄κ²λ€μ ν¨μ ν©μ± μ체λ₯Ό μΆμνν΄μΌ ν©λλ€. κ·Έλ¬λ ν©μ±μ λ²μ£Όλ‘ μ λ³Έμ§μ΄λ―λ‘ λ λ§μ μ½λλ₯Ό μμ±νκΈ° μ μ λ²μ£Ό κ΄μ μμ λ¬Έμ λ₯Ό λΆμν΄ λ³΄κ² μ΅λλ€.
λͺ κ°μ§ μΆκ° ν¨μλ₯Ό νΌκΈ°λ°± νκΈ° μν΄ μ¬λ¬ ν¨μμ λ°ν νμ μ κΎΈλ―Έλ μμ΄λμ΄λ λ§€μ° μ μ©ν κ²μΌλ‘ νλͺ λμμ΅λλ€. μ°λ¦¬λ κ·Έκ²μ ν΄λΉνλ λ λ§μ μμλ₯Ό λ³΄κ² λ κ²μ λλ€. μμμ μ νμ κ³Ό ν¨μμ μΌλ° λ²μ£Όμ λλ€. μ°λ¦¬λ νμ μ κ°μ²΄λ‘ λ¨κ²¨λμ§λ§ μ¬μμ μ₯μλ ν¨μλ‘ μ¬μ μν κ²μ λλ€.
μλ₯Ό λ€μ΄ int
μμ bool
λ‘ κ°λ isEven
ν¨μλ₯Ό κΎΈλ―Έκ³ μΆλ€κ³ κ°μ ν΄λ΄
μλ€. μ°λ¦¬λ κ·Έκ²μ μ₯μλ ν¨μλ‘ ννλλ μ¬μμΌλ‘ λ°κΏλλ€. μ€μν μ μ μ₯μλ ν¨μκ° μμ λ°ννλλΌλ μ΄ μ¬μμ μ¬μ ν int κ°μ²΄μ bool μ¬μ΄μ νμ΄νλ‘ κ°μ£Όνλ€λ κ²μ
λλ€.
pair<bool, string> isEven(int n) {
return make_pair(n % 2 == 0, "isEven ");
}
λ²μ£Όμ λ²μΉμ λ°λΌ μ°λ¦¬λ μ΄ ννλ₯Ό κ°μ²΄ boolμμ 무μμ΄λ κ°λ λ€λ₯Έ μ¬μμΌλ‘ ν©μ±ν μ μμ΄μΌ ν©λλ€. νΉν, μ΄μ negate ν¨μλ‘ ν©μ±ν μ μμ΄μΌ ν©λλ€.
pair<bool, string> negate(bool b) {
return make_pair(!b, "Not so! ");
}
λΆλͺ ν, μ°λ¦¬λ μ λ ₯/μΆλ ₯ λΆμΌμΉ λλ¬Έμ μ΄ λ νμ μ μΌλ° ν¨μλ₯Ό ν©μ±νλ κ²κ³Ό κ°μ λ°©μμΌλ‘ ν©μ±ν μ μμ΅λλ€. ν©μ±μ μλμ κ°μμΌ ν©λλ€.
pair<bool, string> isOdd(int n) {
pair<bool, string> p1 = isEven(n);
pair<bool, string> p2 = negate(p1.first);
return make_pair(p2.first, p1.second + p2.second);
}
κ·Έλμ μ°λ¦¬κ° ν©μ±νκ³ μλ μ΄ μλ‘μ΄ λ²μ£Όμμ λ κ°μ§ μ¬μμ ν©μ±μ λν λ μνΌκ° μμ΅λλ€.
- 첫 λ²μ§Έ μ¬μμ ν΄λΉνλ κΎΈλ©°μ§ ν¨μ μ€ν
- κ²°κ³Ό μμ 첫 λ²μ§Έ μ»΄ν¬λνΈλ₯Ό μΆμΆνκ³ λ λ²μ§Έ μ¬μμ ν΄λΉνλ κΎΈλ©°μ§ ν¨μμ μ λ¬ν©λλ€.
- 첫 λ²μ§Έ κ²°κ³Όμ λ λ²μ§Έ μ»΄ν¬λνΈ(λ¬Έμμ΄)μ λ λ²μ§Έ κ²°κ³Όμ λ λ²μ§Έ μ»΄ν¬λνΈ(λ¬Έμμ΄)λ₯Ό μ°κ²°ν©λλ€.
- μ΅μ’ κ²°κ³Όμ 첫 λ²μ§Έ μ»΄ν¬λνΈμ μ°κ²°λ λ¬Έμμ΄μ κ²°ν©ν μλ‘μ΄ μμ λ°νν©λλ€.
μ΄ ν©μ±μ C++μμ κ³ μ°¨ ν¨μλ‘ μΆμννλ €λ©΄ λ²μ£Όμ μ κ°μ²΄μ ν΄λΉνλ μΈ κ°μ§ νμ μΌλ‘ λ§€κ° λ³μνλ ν νλ¦Ώμ μ¬μ©ν΄μΌ ν©λλ€. κ·μΉμ λ°λΌ ν©μ±ν μ μλ λ κ°μ μ₯μλ ν¨μλ₯Ό μ¬μ©νκ³ μΈ λ²μ§Έ μ₯μλ ν¨μλ₯Ό λ°νν΄μΌ ν©λλ€.
template<class A, class B, class C>
function<Writer<C>(A)> compose(function<Writer<B>(A)> m1,
function<Writer<C>(B)> m2)
{
return [m1, m2](A x) {
auto p1 = m1(x);
auto p2 = m2(p1.first);
return make_pair(p2.first, p1.second + p2.second);
};
}
μ΄μ μ΄μ μμλ‘ λμκ°μ μ΄ μ ν
νλ¦Ώμ μ΄μ©ν΄ toUpper
μ toWords
μ ν©μ±μ ꡬνν μ μμ΅λλ€.
Writer<vector<string>> process(string s) {
return compose<string, string, vector<string>>(toUpper, toWords)(s);
}
compose
ν
νλ¦ΏμΌλ‘ νμ
μ μ λ¬νλ κ²μ μ¬μ ν 볡μ‘ν©λλ€. μ΄λ λ°ν νμ
μΆλ‘ μ΄ μλ μΌλ°νλ λλ€ ν¨μλ₯Ό μ§μνλ C++14 νΈν μ»΄νμΌλ¬λ₯Ό μ¬μ©νλ©΄ νΌν μ μμ΅λλ€. (μ΄ μ½λμ λν ν¬λ λ§μ Eric Nieblerμκ² μμ΅λλ€)
auto const compose = [](auto m1, auto m2) {
return [m1, m2](auto x) {
auto p1 = m1(x);
auto p2 = m2(p1.first);
return make_pair(p2.first, p1.second + p2.second);
};
};
μ΄ μλ‘μ΄ μ μμμ process
μ ꡬνμ μλμ κ°μ΄ κ°λ¨ν΄μ§λλ€.
Writer<vector<string>> process(string s){
return compose(toUpper, toWords)(s);
}
κ·Έλ¬λ μμ§ λλμ§ μμμ΅λλ€. μ°λ¦¬μ μλ‘μ΄ λ²μ£Όμμ ν©μ±μ μ μνμ§λ§, νλ± μ¬μμ 무μμΈκ°μ? μ΄κ²μ μ°λ¦¬μ μΌλ°μ μΈ νλ±ν¨μκ° μλλλ€. μ΄κ²λ€μ A νμ μμ Aνμ μΌλ‘μ μ¬μμ΄μ΄μΌ νλ©° μ΄λ κΎΈλ©°μ§ ν¨μλ€μ νμμ μλ―Έν©λλ€.
Writer<A> identity(A);
μ΄κ²λ€μ ν©μ±κ³Ό κ΄λ ¨νμ¬ unitμ²λΌ λμν΄μΌ ν©λλ€. ν©μ±μ λν μ μλ₯Ό 보면 νλ± μ¬μμ΄ λ³κ²½ μμ΄ μΈμλ₯Ό μ λ¬νκ³ λ‘κ·Έμ λΉ λ¬Έμμ΄λ§ μ 곡ν΄μΌ ν¨μ μ μ μμ΅λλ€.
template<class A>
Writer<A> identity(A x) {
return make_pair(x, "");
}
λ°©κΈ μ μν λ²μ£Όκ° μ€μ λ‘ κ·μΉμ λ°λ₯΄λ λ²μ£Όμμ μ½κ² νμ ν μ μμ΅λλ€. νΉν, μ°λ¦¬μ ν©μ±μ μ¬μνκ² κ²°ν©μ±μ΄ μμ΅λλ€. κ° μμ 첫 λ²μ§Έ μ»΄ν¬λνΈμμ μ΄λ€ μΌμ΄ μΌμ΄λλμ§ λ°λΌκ°λ©΄ κ²°ν©ν μ μλ μΌλ° ν¨μμ ν©μ±μΌ λΏμ λλ€. λ λ²μ§Έ μ»΄ν¬λνΈκ° μ°κ²°λμλ€λ©΄ μ°κ²° λν κ²°ν©μ λλ€.
μ리ν λ
μλ μ΄ κ΅¬μ‘°λ₯Ό λ¬Έμμ΄ λͺ¨λ
Έμ΄λλΏλ§ μλλΌ λͺ¨λ λͺ¨λ
Έμ΄λλ‘ μΌλ°ννλ κ²μ΄ μ½λ€λ κ²μ μ μ μμ΅λλ€. compose
λ΄λΆμ +
λμ mappend
λ₯Ό μ¬μ©νκ³ identity
λ΄λΆμ ""
λμ mempty
λ₯Ό μ¬μ©ν κ²μ
λλ€. λ¬Έμμ΄λ§ κΈ°λ‘νλ κ²μΌλ‘ μ νν μ΄μ λ μμ΅λλ€. μ’μ λΌμ΄λΈλ¬λ¦¬ μμ±μλ λΌμ΄λΈλ¬λ¦¬κ° λμνλλ‘ νλ μ΅μνμ μ μ½ μ‘°κ±΄μ μλ³ν μ μμ΄μΌ ν©λλ€. μ¬κΈ°μ λ‘κΉ
λΌμ΄λΈλ¬λ¦¬μ μ μΌν μꡬ μ¬νμ λ‘κ·Έμ λ¨μΌ μμ±μ΄ μμ΄μΌ νλ€λ κ²μ
λλ€.
Haskellλ‘ μμ±ν λμΌν λ΄μ©μ λ κ°κ²°νλ©° μ»΄νμΌλ¬λ‘λΆν° λ λ§μ λμμ λ°μ΅λλ€. Writer
νμ
μ μ μνλ κ²μΌλ‘ μμνκ² μ΅λλ€.
type Writer a = (a, String)
μ¬κΈ°μμλ C++μ typedef
(λλ using
)μ ν΄λΉνλ νμ
λ³μΉμ μ μνκ³ μμ΅λλ€. Writer
νμ
μ a
νμ
λ³μλ‘ λ§€κ° λ³μνλλ©° a
μ String
μκ³Ό λμΌν©λλ€. μμ λν ꡬ문μ μΌνλ‘ κ΅¬λΆλ κ΄νΈ μμ λ νλͺ©λ§ μμΌλ©° λ¬Έλ²μ΄ μ΅μνλμ΄μμ΅λλ€.
μ°λ¦¬μ μ¬μμ μμμ νμ
μμ μΌλΆ Writer
νμ
μ μ΄λ₯΄λ ν¨μμ
λλ€.
a -> Writer b
μ°λ¦¬λ ν©μ±μ "λ¬Όκ³ κΈ°"λΌκ³ λ νλ μ¬λ―Έμλ μ€μ μ°μ°μλ‘ μ μΈν κ²μ λλ€.
(>=>) :: (a -> Writer b) -> (b -> Writer c) -> (a -> Writer c)
λ κ°μ μΈμλ₯Ό λ°λ ν¨μμ΄λ©°, κ°κ°μ μ체μ μΌλ‘ ν¨μμ΄κ³ ν¨μλ₯Ό λ°νν©λλ€. 첫 λ²μ§Έ μΈμλ (a->Writer b)
νμ
μ΄κ³ λ λ²μ§Έ μΈμλ (b->Writer c)
μ΄λ©° κ²°κ³Όλ (a->Writer c)
μ
λλ€.
μ΄ μ€μ μ°μ°μμ μ μλ μλμ κ°μ΅λλ€. λ κ°μ μΈμ m1
κ³Ό m2
κ° λ¬Όκ³ κΈ° κΈ°νΈμ μμͺ½μ νμλ©λλ€.
m1 >=> m2 = \x ->
let (y, s1) = m1 x
(z, s2) = m2 y
in (z, s1 ++ s2)
κ²°κ³Όλ νλμ μΈμ x
μ λλ€ ν¨μμ
λλ€. λλ€λ λ°± μ¬λμλ‘ μμ±λ©λλ€. λ€λ¦¬κ° μ λ¨λ κ·Έλ¦¬μ€ λ¬Έμ Ξ»λ‘ μκ°νμΈμ.
let
νν μμ μ¬μ©νλ©΄ 보쑰 λ³μλ₯Ό μ μΈν μ μμ΅λλ€. μ¬κΈ°μ m1
μ νΈμΆν κ²°κ³Όλ (y, s1)
λ³μ μμ ν¨ν΄μ μΌμΉλ©λλ€. 첫 λ²μ§Έ ν¨ν΄μ y
μΈμλ₯Ό μ¬μ©ν΄ m2
λ₯Ό νΈμΆν κ²°κ³Όλ (z, s2)
μ μΌμΉν©λλ€.
Haskellμμλ C++μμμ κ°μ΄ μ κ·Όμλ₯Ό μ¬μ©νλ λμ μΌμΉ μμ ν¨ν΄ννλ κ²μ΄ μΌλ°μ μ λλ€. κ·Έ μΈμλ λ ꡬν μ¬μ΄μ λ§€μ° μ§μ μ μΈ λμμ΄ μμ΅λλ€.
let
νν μμ μ 체 κ°μ in μ μ μ§μ λμ΄ μμ΅λλ€. μ¬κΈ°μ μμ 첫 λ²μ§Έ μ»΄ν¬λνΈκ° z
μ΄κ³ λ λ²μ§Έ μ»΄ν¬λνΈκ° λ λ¬Έμμ΄μ μ°κ²°μΈ s1++s2
μ
λλ€.
λν μ°λ¦¬μ λ²μ£Όμ λν νλ± μ¬μμ μ μν κ²μ΄μ§λ§, ν¨μ¬ λμ€μ λͺ
νν΄μ§ μ΄μ λ‘ μ΄κ²μ return
μ΄λΌκ³ λΆλ₯Ό κ²μ
λλ€.
return :: a -> Writer a
return x = (x, "")
μμ±μ μν΄ upCase
λ° toWords
ν¨μμ Haskell λ²μ μ μ¬μ©νκ² μ΅λλ€.
upCase :: String -> Writer String
upCase s = (map toUpper s, "upCase ")
toWords :: String -> Writer [String]
toWords s = (words s, "toWords ")
map
ν¨μλ C++μ transform
μ ν΄λΉν©λλ€. λ¬Έμμ΄ s
μ λ¬Έμ ν¨μ toUpper
λ₯Ό μ μ©ν©λλ€. 보쑰 κΈ°λ₯ words
λ νμ€ Prelude λΌμ΄λΈλ¬λ¦¬μ μ μλμ΄ μμ΅λλ€.
λ§μ§λ§μΌλ‘ λ ν¨μμ ν©μ±μ λ¬Όκ³ κΈ° μ°μ°μμ λμμΌλ‘ μνλ©λλ€.
process :: String -> Writer [String]
process = upCase >=> toWords
μ¬λ¬λΆλ€μ μ κ° κ·Έ μ리μμ μ΄ λ²μ£Όλ₯Ό λ°λͺ νμ§ μμλ€κ³ μ§μνμ κ²μ λλ€. μ΄κ²μ λͺ¨λλλ₯Ό κΈ°λ°μΌλ‘ νλ λ²μ£ΌμΈ Kleisli λ²μ£Όμ μμμ λλ€. μ°λ¦¬λ μμ§ λͺ¨λλμ λν΄ λ Όμν μ€λΉκ° λμ§ μμμ§λ§, λͺ¨λλκ° λ¬΄μμ ν μ μλμ§ λ§λ³΄κ³ μΆμμ΅λλ€. μ νλ λͺ©μ μ μν΄ Kleisli λ²μ£Όμλ κΈ°λ³Έ νλ‘κ·Έλλ° μΈμ΄μ νμ μ΄ κ°μ²΄λ‘ μμ΅λλ€. νμ Aμμ νμ Bλ‘μ μ¬μμ νΉμ κΎΈλ°μ μ¬μ©ν΄ Aμμ Bλ‘ νμλ νμ μΌλ‘ μ΄λνλ ν¨μμ λλ€. κ° Kleisli λ²μ£Όλ κ·Έλ° μ¬μμ μ체μ μΈ ν©μ±κ³Ό ν΄λΉ ν©μ±μ λν νλ± μ¬μμ μ μν©λλ€. (λμ€μ "κΎΈλ°"μ΄λΌλ λΆμ νν μ©μ΄κ° λ²μ£Όμ μλνν°(endofunctor) κ°λ μ ν΄λΉν¨μ μ μ μμ΅λλ€)
μ΄ κΈμμ λ²μ£Όμ κΈ°μ΄λ‘ μ¬μ©ν νΉμ λͺ¨λλλ₯Ό Writer λͺ¨λλλΌκ³ νλ©° ν¨μμ μ€νκ³Ό κΈ°λ‘μ μΆμ νλ λ° μ¬μ©λ©λλ€. λν μμ κ³μ°μ μ΄ννΈλ₯Ό ν¬ν¨νκΈ° μν λ³΄λ€ μΌλ°μ μΈ λ°©λ²μ μμμ΄κΈ°λ ν©λλ€. μ΄μ μ bottomμ 무μνλ©΄ μ§ν© λ²μ£Όμμ νλ‘κ·Έλλ° μΈμ΄ νμ κ³Ό ν¨μλ₯Ό λͺ¨λΈλ§ν μ μμμ 보μμ΅λλ€. μ¬κΈ°μμ μ°λ¦¬λ μ΄ λͺ¨λΈμ μ½κ° λ€λ₯Έ λ²μ£Όλ‘ νμ₯νμ΅λλ€. μ΄ λ²μ£Όλ μ¬μμ΄ κΎΈλ©°μ§ ν¨μλ‘ ννλκ³ κ·Έ ν©μ±μ ν ν¨μμ μΆλ ₯μ λ€λ₯Έ ν¨μμ μ λ ₯μΌλ‘ μ λ¬νλ κ² μ΄μμ μνν©λλ€. μ°λ¦¬λ ν κ°μ§ λ μμ λ‘κ² μ¬μ©ν μ μμ΅λλ€. λ°λ‘ ν©μ± μ체μ λλ€. μ΄κ²μ λͺ λ Ήν μΈμ΄μμ μ ν΅μ μΌλ‘ λΆμμ©μ μ¬μ©νμ¬ κ΅¬νλλ νλ‘κ·Έλ¨μ λ¨μν νκΈ° μλ―Έλ‘ μ λΆμ¬νλ κ²μ κ°λ₯νκ² νλ μ νν μμ λμ λλ€.
μΈμμ κ°λ₯ν λͺ¨λ κ°μ λν΄ μ μλμ§ μμ ν¨μλ₯Ό λΆλΆ ν¨μλΌκ³ ν©λλ€. μνμ μλ―Έμ ν¨μκ° μλλ―λ‘ νμ€ λ²μ£Όν νμ λ§μ§ μμ΅λλ€. κ·Έλ¬λ optional
λ‘ κΎΈλ©°μ§ νμ
μ λ°ννλ ν¨μλ‘ λνλΌ μ μμ΅λλ€.
template<class A> class optional {
bool _isValid;
A _value;
public:
optional() : _isValid(false) {}
optional(A v) : _isValid(true), _value(v) {}
bool isValid() const { return _isValid; }
A value() const { return _value; }
};
μλ₯Ό λ€μ΄, μλλ μ₯μλ ν¨μ safe_root
μ ꡬνμ
λλ€.
optional<double> safe_root(double x) {
if (x >= 0) return optional<double>{sqrt(x)};
else return optional<double>{};
}
λμ ν κ²λ€μ μλμ κ°μ΅λλ€.
- λΆλΆ ν¨μμ λν Kleisli λ²μ£Όλ₯Ό ꡬμ±ν©λλ€. (ν©μ± λ° νλ± μ μ)
- μΈμκ° 0κ³Ό λ€λ₯Έ κ²½μ° μΈμμ μ ν¨ν μμλ₯Ό λ°ννλ κΎΈλ©°μ§ ν¨μ
safe_reciprocal
μ ꡬνν©λλ€. safe_root
μsafe_reciprocal
μ ν©μ±νμ¬ κ°λ₯ν λλ§λ€sqrt(1/x)
λ₯Ό κ³μ°νλsafe_root_reciprocal
μ ꡬνν©λλ€.
μ΄μμ μ½κ³ C++14μ κ³ κΈ κΈ°λ₯μ μ¬μ©νμ¬ νμ
μΆλ‘ μ μ λνλ λ μ’μ compose
μ ꡬνμ μ 곡ν Eric Nieblerμκ² κ°μ¬λ립λλ€. νμ
νΉμ±(type traits)μ μ¬μ©νμ¬ λμΌν μμ
μ μννλ ꡬμ ν
νλ¦Ώ λ§λ²μ μ 체μ μΌλ‘ μλΌλΌ μ μμμ΅λλ€. λͺ κ°μ§ μ€μν μ¬νμ λͺ
νν νλ λ° λμμ΄ λλ μ μ©ν μ견μ μ£Όμ Gershom Bazermanμκ²λ κ°μ¬λ립λλ€.
β¬ λ€λ‘κ°κΈ° / λ€μμΌλ‘ β‘
Translated by @Minsu Kimβ