Last active
December 26, 2015 04:39
-
-
Save whanhee/7095394 to your computer and use it in GitHub Desktop.
Type class: filterable. For explanation, see: http://functionalcpp.wordpress.com/2013/09/18/type-class-filterable/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
#pragma once | |
#include <deque> | |
#include <list> | |
#include <set> | |
#include <string> | |
#include <unordered_set> | |
#include <vector> | |
namespace fc | |
{ | |
template <class C> | |
struct container_traits | |
{ | |
// Type value_type | |
// void add_element(C&,T) | |
// void concat(C&,C) | |
// Type rebind<U> | |
}; | |
template<class C> | |
struct sequence_container_traits; | |
template<template<class,class> class C, class T, class A> | |
struct sequence_container_traits<C<T,A>> | |
{ | |
using value_type = T; | |
static void add_element(C<T,A>& c, const T& t) | |
{ | |
c.push_back(t); | |
} | |
static void concat(C<T,A>& lhs, const C<T,A>& rhs) | |
{ | |
lhs.insert(lhs.end(),rhs.begin(),rhs.end()); | |
} | |
template<class U> | |
using rebind = C<U,typename A::template rebind<U>::other>; | |
}; | |
template<class... Args> | |
struct container_traits<std::deque<Args...>> : public sequence_container_traits<std::deque<Args...>> | |
{}; | |
template<class... Args> | |
struct container_traits<std::list<Args...>> : public sequence_container_traits<std::list<Args...>> | |
{}; | |
template<class... Args> | |
struct container_traits<std::vector<Args...>> : public sequence_container_traits<std::vector<Args...>> | |
{}; | |
template<class C> | |
struct associative_container_traits; | |
template<template<class,class,class> class C, class T, template<class> class O, class A> | |
struct associative_container_traits<C<T,O<T>,A>> | |
{ | |
using value_type = T; | |
static void add_element(C<T,O<T>,A>& c, const T& t) | |
{ | |
c.insert(t); | |
} | |
static void concat(C<T,O<T>,A>& lhs, const C<T,O<T>,A>& rhs) | |
{ | |
lhs.insert(rhs.begin(),rhs.end()); | |
} | |
template<class U> | |
using rebind = C<U,O<U>,typename A::template rebind<U>::other>; | |
}; | |
template<class... Args> | |
struct container_traits<std::multiset<Args...>> : public associative_container_traits<std::multiset<Args...>> | |
{}; | |
template<class... Args> | |
struct container_traits<std::set<Args...>> : public associative_container_traits<std::set<Args...>> | |
{}; | |
template<class C> | |
struct hash_container_traits; | |
template<template<class,class,class,class> class C, class T, template<class> class H, template<class> class O, class A> | |
struct hash_container_traits<C<T,H<T>,O<T>,A>> | |
{ | |
using value_type = T; | |
static void add_element(C<T,H<T>,O<T>,A>& c, const T& t) | |
{ | |
c.insert(t); | |
} | |
static void concat(C<T,H<T>,O<T>,A>& lhs, const C<T,H<T>,O<T>,A>& rhs) | |
{ | |
lhs.insert(rhs.begin(),rhs.end()); | |
} | |
template<class U> | |
using rebind = C<U,H<U>,O<U>,typename A::template rebind<U>::other>; | |
}; | |
template<class... Args> | |
struct container_traits<std::unordered_multiset<Args...>> : public hash_container_traits<std::unordered_multiset<Args...>> | |
{}; | |
template<class... Args> | |
struct container_traits<std::unordered_set<Args...>> : public hash_container_traits<std::unordered_set<Args...>> | |
{}; | |
// basic_string | |
template<class C> | |
struct string_container_traits; | |
template<template<class,class,class> class C, class T, template<class> class K, class A> | |
struct string_container_traits<C<T,K<T>,A>> | |
{ | |
using value_type = T; | |
static void add_element(C<T,K<T>,A>& c, const T& t) | |
{ | |
c.push_back(t); | |
} | |
static void concat(C<T,K<T>,A>& lhs, const C<T,K<T>,A>& rhs) | |
{ | |
lhs+=rhs; | |
} | |
template<class U> | |
using rebind = C<U,K<U>,typename A::template rebind<U>::other>; | |
}; | |
template<class... Args> | |
struct container_traits<std::basic_string<Args...>> : public string_container_traits<std::basic_string<Args...>> | |
{}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
#pragma once | |
#include <type_traits> | |
#include <utility> | |
namespace fc | |
{ | |
template< | |
class F, class... Args, | |
class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type, | |
class = typename std::enable_if<!std::is_member_object_pointer<F>::value>::type | |
> | |
auto eval(F&& f, Args&&... args) -> decltype(f(std::forward<Args>(args)...)) | |
{ | |
return f(std::forward<Args>(args)...); | |
} | |
template<class R, class C, class... Args> | |
auto eval(R(C::*f)() const, const C& c, Args&&... args) -> R | |
{ | |
return (c.*f)(std::forward<Args>(args)...); | |
} | |
template<class R, class C, class... Args> | |
auto eval(R(C::*f)() const, C& c, Args&&... args) -> R | |
{ | |
return (c.*f)(std::forward<Args>(args)...); | |
} | |
template<class R, class C, class... Args> | |
auto eval(R(C::*f)(), C& c, Args&&... args) -> R | |
{ | |
return (c.*f)(std::forward<Args>(args)...); | |
} | |
template<class R, class C> | |
auto eval(R(C::*m), const C& c) -> const R& | |
{ | |
return c.*m; | |
} | |
template<class R, class C> | |
auto eval(R(C::*m), C& c) -> R& | |
{ | |
return c.*m; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
#pragma once | |
#include "foldable.h" | |
namespace fc | |
{ | |
template<class T> | |
struct filterable // : foldable | |
{ | |
// Type value_type | |
// filterable<A> filter(bool(A),filterable<A>) | |
static constexpr bool is_instance = false; | |
}; | |
// Convenience functions | |
template<class F, class T> | |
auto filter(F&& f, const T& in) | |
{ | |
return filterable<T>::filter(std::forward<F>(f),in); | |
} | |
// container instances | |
template<class T> | |
struct default_container_filterable : public foldable<T> | |
{ | |
// Type value_type | |
using value_type = typename ::fc::container_traits<T>::value_type; | |
// filterable<A> filter(bool(A),filterable<A>) | |
template<class F> | |
static auto filter(F&& f, const T& in) -> T | |
{ | |
T out; | |
for (auto& a : in) | |
if (::fc::eval(f,a)) | |
::fc::container_traits<T>::add_element(out,a); | |
return out; | |
} | |
static constexpr bool is_instance = false; | |
}; | |
#define FC_DEFAULT_CONTAINER_FILTERABLE(T)\ | |
template<class... Args>\ | |
struct filterable<T<Args...>> : public default_container_filterable<T<Args...>>\ | |
{}; | |
FC_DEFAULT_CONTAINER_FILTERABLE(std::deque); | |
FC_DEFAULT_CONTAINER_FILTERABLE(std::list); | |
FC_DEFAULT_CONTAINER_FILTERABLE(std::multiset); | |
FC_DEFAULT_CONTAINER_FILTERABLE(std::set); | |
FC_DEFAULT_CONTAINER_FILTERABLE(std::basic_string); | |
FC_DEFAULT_CONTAINER_FILTERABLE(std::unordered_multiset); | |
FC_DEFAULT_CONTAINER_FILTERABLE(std::unordered_set); | |
FC_DEFAULT_CONTAINER_FILTERABLE(std::vector); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
#pragma once | |
#include <memory> | |
#include "container_traits.h" | |
#include "eval.h" | |
#include "monoid.h" | |
namespace fc | |
{ | |
template<class T> | |
struct foldable | |
{ | |
// Type value_type | |
// A fold(foldable<A>) requires monoid<A> | |
// B lfold(B(B,A),B,foldable<A>) | |
static constexpr bool is_instance = false; | |
}; | |
// Convenience functions | |
template<class T> | |
auto fold(const T& in) | |
{ | |
return foldable<T>::fold(in); | |
} | |
template<class F, class B, class T> | |
auto lfold(F&& f, B&& b, const T& in) | |
{ | |
return foldable<T>::lfold(std::forward<F>(f),std::forward<B>(b),in); | |
} | |
// shared_ptr instance | |
template<class T> | |
struct foldable<std::shared_ptr<T>> | |
{ | |
// Type value_type | |
using value_type = T; | |
// A fold(foldable<A>) requires monoid<A> | |
template< | |
class T_, | |
class = typename std::enable_if<std::is_same<T,T_>::value>, | |
class = typename std::enable_if<monoid<T>::is_instance>::type> | |
static auto fold(const T_& in) | |
{ | |
if (in) | |
return monoid<T>::append(monoid<T>::empty(),*in); | |
return monoid<T>::empty(); | |
} | |
// B lfold(B(B,A),B,foldable<A>) | |
template<class F, class B> | |
static auto lfold(F&& f, B b, const std::shared_ptr<T>& in) -> B | |
{ | |
if (in) | |
b = eval(f,b,*in); | |
return b; | |
} | |
static constexpr bool is_instance = true; | |
}; | |
// container instances | |
template<class T> | |
struct default_container_foldable | |
{ | |
// Type value_type | |
using value_type = typename container_traits<T>::value_type; | |
// A fold(foldable<A>) requires monoid<A> | |
template< | |
class T_, | |
class = typename std::enable_if<std::is_same<T,T_>::value>, | |
class = typename std::enable_if<monoid<typename container_traits<T_>::value_type>::is_instance>::type> | |
static auto fold(const T_& in) | |
{ | |
using A = typename container_traits<T_>::value_type; | |
return lfold(monoid<A>::append,monoid<A>::empty(),in); | |
} | |
// B lfold(B(B,A),B,foldable<A>) | |
template<class F, class B> | |
static auto lfold(F&& f, B b, const T& in) -> B | |
{ | |
for (auto& a : in) | |
b = eval(f,b,a); | |
return b; | |
} | |
static constexpr bool is_instance = true; | |
}; | |
#define FC_DEFAULT_CONTAINER_FOLDABLE(T)\ | |
template<class... Args>\ | |
struct foldable<T<Args...>> : public default_container_foldable<T<Args...>>\ | |
{}; | |
FC_DEFAULT_CONTAINER_FOLDABLE(std::deque); | |
FC_DEFAULT_CONTAINER_FOLDABLE(std::list); | |
FC_DEFAULT_CONTAINER_FOLDABLE(std::multiset); | |
FC_DEFAULT_CONTAINER_FOLDABLE(std::set); | |
FC_DEFAULT_CONTAINER_FOLDABLE(std::basic_string); | |
FC_DEFAULT_CONTAINER_FOLDABLE(std::unordered_multiset); | |
FC_DEFAULT_CONTAINER_FOLDABLE(std::unordered_set); | |
FC_DEFAULT_CONTAINER_FOLDABLE(std::vector); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
// Build using -std=gnu++1y | |
#include <iostream> | |
#include <functional> | |
#include <locale> | |
#include "foldable.h" | |
#include "filterable.h" | |
#include "mappable.h" | |
#include "monoid.h" | |
#include "rfoldable.h" | |
#include "zip.h" | |
struct Person | |
{ | |
std::string name; | |
int age; | |
double income; | |
}; | |
double mean_20s_income(const std::vector<Person>& people) | |
{ | |
auto in_20s = [](const Person& p){return p.age < 30 && p.age >= 20;}; | |
auto get_mean = [n=0](double last_mean, double income) mutable | |
{ | |
++n; | |
return last_mean*(n-1)/n + (double)income/n; | |
}; | |
return fc::lfold(get_mean,0.0,fc::map(&Person::income,fc::filter(in_20s,people))); | |
} | |
int main() | |
{ | |
std::vector<int> numbers{0,1,2,3,4,5,6,7,8,9,10}; | |
// filter using lfold | |
auto append_even = [](std::vector<int> ns, int n) | |
{ | |
if (n % 2 == 0) ns.push_back(n); | |
return ns; | |
}; | |
for (int n : fc::lfold(append_even,std::vector<int>{},numbers)) | |
std::cout << n << " "; | |
std::cout << "\n"; | |
// filter using map and fold | |
auto to_even_vector = [](int n){ | |
if (n % 2 == 0) | |
return std::vector<int>{n}; | |
return std::vector<int>{}; | |
}; | |
for (int n : fc::fold(fc::map(to_even_vector,numbers))) | |
std::cout << n << " "; | |
std::cout << "\n"; | |
// filter | |
auto is_even = [](int n){return n % 2 == 0;}; | |
for (int n : fc::filter(is_even,numbers)) | |
std::cout << n << " "; | |
std::cout << "\n"; | |
// stuff | |
std::vector<Person> people{ | |
{"Ashley",19,10.5}, | |
{"Betty",22,15}, | |
{"Chris",23,17.25}, | |
{"Daniel",27,31}, // <- balling | |
{"Elissa",30,22}, | |
{"Frank",24,16} | |
}; | |
std::cout << "mean income " << mean_20s_income(people) << "\n"; | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
#pragma once | |
#include <memory> | |
#include "container_traits.h" | |
#include "tuple.h" | |
#include "tuple_eval.h" | |
namespace fc | |
{ | |
// remove const, volatile and references | |
template<class T> | |
using remove_cv_ref = typename std::remove_cv<typename std::remove_reference<T>::type>::type; | |
template<class T> | |
struct mappable | |
{ | |
// Type value_type | |
// mappable<R> map(R(A),mappable<A>) | |
static constexpr bool is_instance = false; | |
}; | |
// Convenience functions | |
template<class F, class T, class... Args> | |
auto map(F&& f, const T& in, const Args&... args) | |
{ | |
return mappable<T>::map(std::forward<F>(f),in,args...); | |
} | |
// Function instances | |
template<class Result,class... Params> | |
struct mappable<Result(Params...)> | |
{ | |
// Type value_type | |
using value_type = Result; | |
// mappable<R> map(R(A,Args...),mappable<A>,mappable<Args>...) | |
template<class F,class A,class... Args> | |
static auto map(F&& f, const A& in, const Args&... args) | |
{ | |
auto t_funcs = std::make_tuple(in,args...); | |
return [f,t_funcs](Params... params) | |
{ | |
return tuple_eval(f, | |
multi_tuple_eval(t_funcs,std::forward_as_tuple(params...)) | |
); | |
}; | |
} | |
static constexpr bool is_instance = true; | |
}; | |
// const member function | |
template<class Result, class Class, class... Params> | |
struct mappable<Result(Class::*)(Params...) const> : | |
public mappable<Result(const Class&,Params...)> | |
{}; | |
// member function | |
template<class Result, class Class, class... Params> | |
struct mappable<Result(Class::*)(Params...)> : | |
public mappable<Result(Class&,Params...)> | |
{}; | |
// member object | |
template<class Result, class Class> | |
struct mappable<Result(Class::*)> : | |
public mappable<Result(const Class&)> | |
{}; | |
// free function | |
template<class Result, class... Params> | |
struct mappable<Result(*)(Params...)> : | |
public mappable<Result(Params...)> | |
{}; | |
// shared_ptr instance | |
template<class T> | |
struct mappable<std::shared_ptr<T>> | |
{ | |
// Type value_type | |
using value_type = T; | |
// mappable<R> map(R(A,Args...),mappable<A>,mappable<Args>...) | |
template<class F,class A,class... Args> | |
static auto map(F&& f, const std::shared_ptr<A>& in, const std::shared_ptr<Args>&... args) | |
-> std::shared_ptr<remove_cv_ref<decltype(eval(f,*in,(*args)...))>> | |
{ | |
if (!tuple_all_valid(std::forward_as_tuple(in,args...))) | |
return std::shared_ptr<remove_cv_ref<decltype(eval(f,*in,(*args)...))>>(); | |
return std::make_shared<remove_cv_ref<decltype(eval(f,*in,(*args)...))>>( | |
std::move(eval(std::forward<F>(f),*in,(*args)...))); | |
} | |
static constexpr bool is_instance = true; | |
}; | |
// container instances | |
template<class T> | |
struct default_container_mappable | |
{ | |
// Type value_type | |
using value_type = typename container_traits<T>::value_type; | |
// mappable<R> map(R(A,Args...),mappable<A>,mappable<Args>...) | |
template<class F,class A,class... Args> | |
static auto map(F&& f, const A& in, const Args&... args) | |
-> typename container_traits<T>::template rebind< | |
remove_cv_ref<decltype(eval(f, | |
std::declval<typename container_traits<A>::value_type>(), | |
std::declval<typename container_traits<Args>::value_type>()... | |
))>> | |
{ | |
using B = remove_cv_ref<decltype(eval(f, | |
std::declval<typename container_traits<A>::value_type>(), | |
std::declval<typename container_traits<Args>::value_type>()... | |
))>; | |
using T_B = typename container_traits<T>::template rebind<B>; | |
T_B out; | |
const auto ends = std::make_tuple(in.end(),(args.end())...); | |
for (auto iters = std::make_tuple(in.begin(),(args.begin())...); | |
!tuple_any_equal(iters,ends); | |
tuple_increment(iters)) | |
{ | |
container_traits<T_B>::add_element(out,tuple_eval(std::forward<F>(f),tuple_dereference(iters))); | |
} | |
return out; | |
} | |
static constexpr bool is_instance = true; | |
}; | |
#define FC_DEFAULT_CONTAINER_MAPPABLE(T)\ | |
template<class... Args>\ | |
struct mappable<T<Args...>> : public default_container_mappable<T<Args...>>\ | |
{}; | |
FC_DEFAULT_CONTAINER_MAPPABLE(std::deque); | |
FC_DEFAULT_CONTAINER_MAPPABLE(std::list); | |
FC_DEFAULT_CONTAINER_MAPPABLE(std::multiset); | |
FC_DEFAULT_CONTAINER_MAPPABLE(std::set); | |
FC_DEFAULT_CONTAINER_MAPPABLE(std::basic_string); | |
FC_DEFAULT_CONTAINER_MAPPABLE(std::unordered_multiset); | |
FC_DEFAULT_CONTAINER_MAPPABLE(std::unordered_set); | |
FC_DEFAULT_CONTAINER_MAPPABLE(std::vector); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
#pragma once | |
#include "container_traits.h" | |
namespace fc | |
{ | |
template<class T> | |
struct monoid | |
{ | |
// T empty() | |
// T append(T,T) | |
static constexpr bool is_instance = false; | |
}; | |
// Convenience functions | |
template<class T> | |
T append(const T& lhs, const T& rhs) | |
{ | |
return monoid<T>::append(lhs,rhs); | |
} | |
// Fundamental type instances | |
template<class T> | |
struct default_fundamental_type_monoid | |
{ | |
static T empty(){return T{};} | |
static T append(const T& lhs, const T& rhs){return lhs+rhs;} | |
static constexpr bool is_instance = true; | |
}; | |
#define FUNDAMENTAL_TYPES\ | |
X(bool)\ | |
X(signed char)\ | |
X(unsigned char)\ | |
X(char)\ | |
X(wchar_t)\ | |
X(char16_t)\ | |
X(char32_t)\ | |
X(short)\ | |
X(unsigned short)\ | |
X(int)\ | |
X(unsigned)\ | |
X(long)\ | |
X(unsigned long)\ | |
X(long long)\ | |
X(unsigned long long) | |
#define FC_DEFAULT_FUNDAMENTAL_TYPE_MONOID(T)\ | |
template<>\ | |
struct monoid<T> : public default_fundamental_type_monoid<T>\ | |
{}; | |
#define X FC_DEFAULT_FUNDAMENTAL_TYPE_MONOID | |
FUNDAMENTAL_TYPES; | |
#undef X | |
// Container instances | |
template<class T> | |
struct default_container_monoid | |
{ | |
// T empty() | |
static T empty(){return T{};} | |
// T append(T,T) | |
static T append(T lhs, const T& rhs) | |
{ | |
container_traits<T>::concat(lhs,rhs); | |
return lhs; | |
} | |
static constexpr bool is_instance = true; | |
}; | |
#define FC_DEFAULT_CONTAINER_MONOID(T)\ | |
template<class... Args>\ | |
struct monoid<T<Args...>> : public default_container_monoid<T<Args...>>\ | |
{}; | |
FC_DEFAULT_CONTAINER_MONOID(std::deque); | |
FC_DEFAULT_CONTAINER_MONOID(std::list); | |
FC_DEFAULT_CONTAINER_MONOID(std::multiset); | |
FC_DEFAULT_CONTAINER_MONOID(std::set); | |
FC_DEFAULT_CONTAINER_MONOID(std::basic_string); | |
FC_DEFAULT_CONTAINER_MONOID(std::unordered_multiset); | |
FC_DEFAULT_CONTAINER_MONOID(std::unordered_set); | |
FC_DEFAULT_CONTAINER_MONOID(std::vector); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
#pragma once | |
#include "foldable.h" | |
namespace fc | |
{ | |
template<class T> | |
struct rfoldable // : foldable | |
{ | |
// Type value_type | |
// B rfold(B(A,B),B,foldable<A>) | |
static constexpr bool is_instance = false; | |
}; | |
// Convenience functions | |
template<class F, class B, class T> | |
auto rfold(F&& f, B&& b, const T& in) | |
{ | |
return rfoldable<T>::rfold(std::forward<F>(f),std::forward<B>(b),in); | |
} | |
// shared_ptr instance | |
template<class T> | |
struct rfoldable<std::shared_ptr<T>> : public foldable<std::shared_ptr<T>> | |
{ | |
// Type value_type | |
using value_type = T; | |
// B rfold(B(A,B),B,foldable<A>) | |
template<class F, class B> | |
static auto rfold(F&& f, B b, const std::shared_ptr<T>& in) -> B | |
{ | |
if (in) | |
b = ::fc::eval(f,b,*in); | |
return b; | |
} | |
static constexpr bool is_instance = true; | |
}; | |
// container instances | |
template<class T> | |
struct default_container_rfoldable : public foldable<T> | |
{ | |
// Type value_type | |
using value_type = typename ::fc::container_traits<T>::value_type; | |
// B rfold(B(A,B),B,foldable<A>) | |
template<class F, class B> | |
static auto rfold(F&& f, B b, const T& in) -> B | |
{ | |
for (auto a_it = in.rbegin(); a_it != in.rend(); ++a_it) | |
b = ::fc::eval(f,*a_it,b); | |
return b; | |
} | |
static constexpr bool is_instance = true; | |
}; | |
#define FC_DEFAULT_CONTAINER_RFOLDABLE(T)\ | |
template<class... Args>\ | |
struct rfoldable<T<Args...>> : public default_container_rfoldable<T<Args...>>\ | |
{}; | |
FC_DEFAULT_CONTAINER_RFOLDABLE(std::deque); | |
FC_DEFAULT_CONTAINER_RFOLDABLE(std::list); | |
FC_DEFAULT_CONTAINER_RFOLDABLE(std::multiset); | |
FC_DEFAULT_CONTAINER_RFOLDABLE(std::set); | |
FC_DEFAULT_CONTAINER_RFOLDABLE(std::basic_string); | |
FC_DEFAULT_CONTAINER_RFOLDABLE(std::unordered_multiset); | |
FC_DEFAULT_CONTAINER_RFOLDABLE(std::unordered_set); | |
FC_DEFAULT_CONTAINER_RFOLDABLE(std::vector); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
#pragma once | |
#include <tuple> | |
namespace fc | |
{ | |
template<size_t index> | |
struct tuple_helper | |
{ | |
template<class... Args> | |
static bool any_equal(const std::tuple<Args...>& lhs, const std::tuple<Args...>& rhs) | |
{ | |
if (std::get<index>(lhs) == std::get<index>(rhs)) | |
return true; | |
return tuple_helper<index-1>::any_equal(lhs,rhs); | |
} | |
template<class... Args> | |
static void increment(std::tuple<Args...>& a) | |
{ | |
tuple_helper<index-1>::increment(a); | |
std::get<index>(a)++; | |
} | |
template<class Tuple,class... Args> | |
static auto dereference(Tuple&& t, Args&&... args) | |
{ | |
return tuple_helper<index-1>::dereference( | |
std::forward<Tuple>(t), | |
std::get<index>(std::forward<Tuple>(t)), | |
std::forward<Args>(args)... | |
); | |
} | |
template<class... Args> | |
static bool all_valid(const std::tuple<Args...>& a) | |
{ | |
return bool(std::get<index>(a)) && tuple_helper<index-1>::all_valid(a); | |
} | |
}; | |
template<> | |
struct tuple_helper<0> | |
{ | |
template<class... Args> | |
static bool any_equal(const std::tuple<Args...>& lhs, const std::tuple<Args...>& rhs) | |
{ | |
return std::get<0>(lhs) == std::get<0>(rhs); | |
} | |
template<class... Args> | |
static void increment(std::tuple<Args...>& a) | |
{ | |
std::get<0>(a)++; | |
} | |
template<class Tuple,class... Args> | |
static auto dereference(Tuple&& t, Args&&... args) | |
{ | |
return std::tuple<decltype(*std::get<0>(t)),decltype(*args)...>(*std::get<0>(t),(*args)...); | |
} | |
template<class... Args> | |
static bool all_valid(const std::tuple<Args...>& a) | |
{ | |
return bool(std::get<0>(a)); | |
} | |
}; | |
template<class A,class... Args> | |
bool tuple_any_equal(const std::tuple<A,Args...>& lhs, const std::tuple<A,Args...>& rhs) | |
{ | |
return tuple_helper<sizeof...(Args)>::any_equal(lhs,rhs); | |
} | |
template<class A,class... Args> | |
void tuple_increment(std::tuple<A,Args...>& a) | |
{ | |
tuple_helper<sizeof...(Args)>::increment(a); | |
} | |
template<class Tuple> | |
auto tuple_dereference(Tuple&& t) | |
{ | |
return tuple_helper<std::tuple_size<typename std::remove_reference<Tuple>::type>::value-1>::dereference(std::forward<Tuple>(t)); | |
} | |
template<class A,class... Args> | |
bool tuple_all_valid(const std::tuple<A,Args...>& a) | |
{ | |
return tuple_helper<sizeof...(Args)>::all_valid(a); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
#pragma once | |
#include <tuple> | |
#include "eval.h" | |
namespace fc | |
{ | |
template<size_t index> | |
struct tuple_eval_helper | |
{ | |
template<class Func,class TArgs,class... Args> | |
static auto evaluate(Func&& f, TArgs&& t_args, Args&&... args) | |
-> decltype(tuple_eval_helper<index-1>::evaluate( | |
std::forward<Func>(f), | |
std::forward<TArgs>(t_args), | |
std::get<index>(std::forward<TArgs>(t_args)), | |
std::forward<Args>(args)... | |
)) | |
{ | |
return tuple_eval_helper<index-1>::evaluate( | |
std::forward<Func>(f), | |
std::forward<TArgs>(t_args), | |
std::get<index>(std::forward<TArgs>(t_args)), | |
std::forward<Args>(args)... | |
); | |
} | |
}; | |
template<> | |
struct tuple_eval_helper<0> | |
{ | |
template<class Func,class TArgs,class... Args> | |
static auto evaluate(Func&& f, TArgs&& t_args, Args&&... args) | |
-> decltype(eval( | |
std::forward<Func>(f), | |
std::get<0>(std::forward<TArgs>(t_args)), | |
std::forward<Args>(args)... | |
)) | |
{ | |
return eval( | |
std::forward<Func>(f), | |
std::get<0>(std::forward<TArgs>(t_args)), | |
std::forward<Args>(args)... | |
); | |
} | |
}; | |
template<class Func,class TArgs> | |
auto tuple_eval(Func&& f, TArgs&& t_args) | |
-> decltype(tuple_eval_helper<std::tuple_size< | |
typename std::remove_reference<TArgs>::type>::value-1>::evaluate( | |
std::forward<Func>(f), | |
std::forward<TArgs>(t_args) | |
)) | |
{ | |
return tuple_eval_helper<std::tuple_size< | |
typename std::remove_reference<TArgs>::type>::value-1>::evaluate( | |
std::forward<Func>(f), | |
std::forward<TArgs>(t_args) | |
); | |
} | |
template<size_t index> | |
struct multi_tuple_eval_helper | |
{ | |
template<class TFuncs,class TArgs,class... Results> | |
static auto evaluate(TFuncs&& t_funcs, TArgs&& t_args, Results&&... results) | |
-> decltype(multi_tuple_eval_helper<index-1>::evaluate( | |
std::forward<TFuncs>(t_funcs), | |
std::forward<TArgs>(t_args), | |
tuple_eval(std::get<index>(t_funcs),t_args), | |
std::forward<Results>(results)... | |
)) | |
{ | |
return multi_tuple_eval_helper<index-1>::evaluate( | |
std::forward<TFuncs>(t_funcs), | |
std::forward<TArgs>(t_args), | |
tuple_eval(std::get<index>(t_funcs),t_args), | |
std::forward<Results>(results)... | |
); | |
} | |
}; | |
template<> | |
struct multi_tuple_eval_helper<0> | |
{ | |
template<class TFuncs,class TArgs,class... Results> | |
static auto evaluate(TFuncs&& t_funcs, TArgs&& t_args, Results&&... results) | |
-> decltype(std::tuple<decltype(tuple_eval(std::get<0>(t_funcs),t_args)),Results...>( | |
tuple_eval(std::get<0>(t_funcs),t_args), | |
std::forward<Results>(results)... | |
)) | |
{ | |
return std::tuple<decltype(tuple_eval(std::get<0>(t_funcs),t_args)),Results...>( | |
tuple_eval(std::get<0>(t_funcs),t_args), | |
std::forward<Results>(results)... | |
); | |
} | |
}; | |
template<class TFuncs,class TArgs> | |
auto multi_tuple_eval(TFuncs&& t_funcs, TArgs&& t_args) | |
-> decltype(multi_tuple_eval_helper<std::tuple_size< | |
typename std::remove_reference<TFuncs>::type>::value-1>::evaluate( | |
std::forward<TFuncs>(t_funcs), | |
std::forward<TArgs>(t_args) | |
)) | |
{ | |
return multi_tuple_eval_helper<std::tuple_size< | |
typename std::remove_reference<TFuncs>::type>::value-1>::evaluate( | |
std::forward<TFuncs>(t_funcs), | |
std::forward<TArgs>(t_args) | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2013, Daniel Park | |
* All rights reserved. | |
* | |
* Permission to modify and redistribute this software is granted to | |
* anyone provided the above copyright notice, this condition and the | |
* following disclaimer are retained. | |
* | |
* This software is provided "as is", without and express or implied | |
* warranty. In no event shall the author be liable for damages arising | |
* from the use of this software. | |
*/ | |
#pragma once | |
#include <type_traits> | |
#include <tuple> | |
namespace fc | |
{ | |
struct zipper | |
{ | |
template<class... Args> | |
auto operator()(Args&&... args) | |
{ | |
return std::make_tuple(std::forward<Args>(args)...); | |
} | |
}; | |
struct pairer | |
{ | |
template<class L,class R> | |
auto operator()(L&& l, R&& r) | |
{ | |
return std::make_pair(std::forward<L>(l),std::forward<R>(r)); | |
} | |
}; | |
template<class... Args> | |
struct zipper_t | |
{ | |
template<class... Args_> | |
auto operator()(Args_&&... args) | |
{ | |
return std::tuple<Args...>(std::forward<Args_>(args)...); | |
} | |
}; | |
template<class L,class R> | |
struct pairer_t | |
{ | |
template<class L_,class R_> | |
auto operator()(L_&& l, R_&& r) | |
{ | |
return std::pair<L,R>(std::forward<L_>(l),std::forward<R_>(r)); | |
} | |
}; | |
template<class T> | |
struct make | |
{ | |
template<class... Args> | |
auto operator()(Args&&... args) | |
{ | |
return T(std::forward<Args...>(args...)); | |
} | |
}; | |
#define FC_BINARY_OPERATORS\ | |
X(plus,+)\ | |
X(minus,-)\ | |
X(multiplies,*)\ | |
X(divides,/)\ | |
X(modulus,%)\ | |
X(equal_to,==)\ | |
X(not_equal_to,!=)\ | |
X(greater,>)\ | |
X(less,<)\ | |
X(greater_equal,>=)\ | |
X(less_equal,<=)\ | |
X(logical_and,&&)\ | |
X(logical_or,||)\ | |
X(bit_and,&)\ | |
X(bit_or,|)\ | |
X(bit_xor,^) | |
#define X(name,symbol)\ | |
struct name\ | |
{\ | |
template<class L,class R>\ | |
auto operator()(L&& l, R&& r)\ | |
{\ | |
return l symbol r;\ | |
}\ | |
}; | |
FC_BINARY_OPERATORS | |
#undef X | |
template<class L,class R> | |
auto unpair(std::vector<std::pair<L,R>>&& v) | |
{ | |
std::pair<std::vector<L>,std::vector<R>> out; | |
for (auto& p : v) | |
{ | |
out.first.push_back(p.first); | |
out.second.push_back(p.second); | |
} | |
return out; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment