Skip to content

Instantly share code, notes, and snippets.

@wecing
Created May 3, 2015 07:10
Show Gist options
  • Save wecing/172ace00a4ea807215d4 to your computer and use it in GitHub Desktop.
Save wecing/172ace00a4ea807215d4 to your computer and use it in GitHub Desktop.
Sum and Product monoid in C++
#include <iostream>
#include <cstdlib>
#include <memory>
#include <vector>
#include <string>
template<typename M, typename T>
class SemiGroup {
protected:
T m_t;
public:
SemiGroup(T t) : m_t(t) {}
SemiGroup<M,T> mappend(SemiGroup<M,T> other);
T get() { return m_t; }
};
template<typename M, typename T>
class Monoid : public SemiGroup<M,T> {
public:
Monoid(T t) : SemiGroup<M,T>(t) {}
static Monoid<M,T> mzero;
};
class Sum {};
template<>
SemiGroup<Sum, int> SemiGroup<Sum, int>::mappend(SemiGroup<Sum, int> other) {
return SemiGroup<Sum, int>(m_t + other.m_t);
}
template<>
Monoid<Sum, int> Monoid<Sum, int>::mzero = Monoid<Sum, int>(0);
class Product {};
template<>
SemiGroup<Product, int> SemiGroup<Product, int>::mappend(SemiGroup<Product, int> other) {
return SemiGroup<Product, int>(m_t * other.m_t);
}
template<>
Monoid<Product, int> Monoid<Product, int>::mzero = Monoid<Product, int>(1);
template<typename M, typename T>
Monoid<M, T> mconcat(const std::vector<T> & vals) {
Monoid<M, T> r = Monoid<M, T>::mzero;
for (auto v : vals) {
r = Monoid<M, T>(r.mappend(v).get());
}
return r;
}
int main(void) {
std::vector<int> vals{3, 5};
std::cout << "Sum::mconcat [3,5] == "
<< mconcat<Sum,int>(vals).get()
<< std::endl;
std::cout << "Product::mconcat [3,5] == "
<< mconcat<Product,int>(vals).get()
<< std::endl;
return 0;
}
@wecing
Copy link
Author

wecing commented May 3, 2015

(心悦诚服(但是你的写法比我的长啊))@darkfall

@darkfall
Copy link

darkfall commented May 3, 2015

(睡前意识模糊状态下的, 其实没啥卵区别, 除了variadic template可以传任意多个参数进去而不用构造list, 几个模板单独出来个人觉得扩展比较方便, 这样就不用偏特化你的类而是几个trait模板(不用在意那些细节( @wecing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment