For educational reasons, I'm trying to implement a maybe monad in C++14. My (perhaps overly simplistic) understanding of monads is that they let you define a computation as a series of composable function calls. The wikipedia article on monads calls them "programmable semicolons" because they let you define what happens between what would otherwise be a set of discreet function calls. The maybe monad is a monad that interrupts computation if a failure occurs.
template<class T>
struct maybe
{
maybe( const T& t ) : argument( t ), valid( true ) {}
maybe() : argument(), valid( false ) {}
T argument;
bool valid;
};
template<class T>
maybe<T> just( const T& t ) { return maybe<T>(t); }
template<class T>
maybe<T> nothing() { return maybe<T>(); }
auto terminal_maybe = [] ( auto term ) {
return [=] ( auto func ) {
return func( term );
};
};
auto fmap_maybe = [] ( auto f ) {
return [=] ( auto t ) {
if( t.valid ) {
try {
t.argument = f( t.argument );
printf("argument = %d\n",t.argument);
}
catch(...) {
t.valid = false;
}
}
return (t.valid) ? terminal_maybe( just( t.argument ) ) : terminal_maybe( nothing<decltype(t.argument)>() );
};
};
int main( int argc, char* argv[] )
{
auto plus_2 = [] ( auto arg ) { return arg + 2; };
auto minus_2 = [] ( auto arg ) { return arg - 2; };
maybe<int> forty = just(40);
terminal_maybe(forty)
(fmap_maybe( plus_2 ))
(fmap_maybe( plus_2 ));
printf("result = %d\n",forty.argument);
return 0;
}
As you can see I am super close! I can chain multiple calls together monadically (and I can tell from printf that my value does what I expect (increments from 40 to 42 and then from 42 to 44)). The problem is that I have no way to get the final value OUT! I tried making terminal_maybe accept a reference (auto&) and that forced me to modify fmap's return statement (to just return terminal_maybe( t ) rather than a new maybe). But it still didn't have the correct value for the final printf.
This works, but I don't know if it makes sense from a FP point of view.
auto unwrap = [](auto const &f) {
return f;
};
int main( int argc, char* argv[] )
{
auto plus_2 = [] ( auto arg ) { return arg + 2; };
auto minus_2 = [] ( auto arg ) { return arg - 2; };
maybe<int> forty = just(40);
auto const &outv = terminal_maybe(forty)
(fmap_maybe( plus_2 ))
(fmap_maybe( plus_2 ))
(unwrap);
std::printf("result = %d\n",outv.argument);
return 0;
}
Related
In my code I have a number of places where I need to take an std::vector of things and put it into a std::map indexed by something. For example here are two code snippets:
//sample A
std::map<Mode::Type, std::vector<Mode>> modesByType;
for( const auto& mode : _modes ) {
Mode::Type type = mode.getType();
auto it = modesByType.find( type );
if( it == modesByType.end() ) {
std::vector<Mode> v = { mode };
modesByType.insert( std::pair( type, v ) );
} else {
it->second.push_back( mode );
}
}
//sample B
std::map<unsigned, std::vector<Category>> categoriesByTab;
for( const auto& category : _categories ) {
unsigned tabIndex = category.getTab();
auto it = categoriesByTab.find( tabIndex );
if( it == categoriesByTab.end() ) {
std::vector<Category> v = { category };
categoriesByTab.insert( std::pair( tabIndex, v ) );
} else {
it->second.push_back( category );
}
}
I'd like to generalize this and create a template function like:
template<typename T, typename V>
std::map<T,std::vector<V>> getMapByType( const std::vector<V>& items, ?? ) {
std::map<T,std::vector<V>> itemsByType;
for( const auto& item : items ) {
unsigned index = ??;
auto it = itemsByType.find( index );
if( it == itemsByType.end() ) {
std::vector<V> v = { item };
itemsByType.insert( std::pair( index, v ) );
} else {
it->second.push_back( item );
}
}
return itemsByType;
}
My question is, how do I define the ?? argument to this function so that I can call the correct V.foo() function to get the index value for the map?
Note, I do not want to make all the classes that this template (V) accepts, inherit from a base class. Can I somehow specify a lambda argument?
have a pointer to a member fn as an extra parameter
template<typename T, typename V>
std::map<T,std::vector<V>> getMapByType( const std::vector<V>& items, T (V::*fn)()const) {
std::map<T,std::vector<V>> itemsByType;
for( const auto& item : items ) {
T index = (item.*fn)();
auto it = itemsByType.find( index );
if( it == itemsByType.end() ) {
std::vector<V> v = { item };
itemsByType.emplace( index, v );
} else {
it->second.push_back( item );
}
}
return itemsByType;
}
auto res = getMapByType(items, &Category::getTab);
You can pass a function that determines the key, something like this:
template <typename V,typename F>
auto getMapByType( const std::vector<V>& items,F func) {
using key_t = std::decay_t<delctype(func(item[0]))>;
std::map<key_t,std::vector<V>> result;
for (const auto& item : items) {
result[ func(item) ].push_back(item);
}
return item;
}
Then you can call it like this
std:vector<Category> vec;
auto m = getMapByType( vec, [](const Category& c) { return c.getTab(); });
or
std:vector<Mode> vec;
auto m = getMapByType( vec, [](const Category& c) { return c.getType(); });
Note that operator[] does already what you reimplemented. It tries to find an element with the given key. If none is present it inserts a default constructed one, then it returns a reference to the mapped value.
Even without operator[] you do not need find and then insert, because insert does only insert when no element with given key was present. insert returns an iterator to the element and a bool which tells you if the insertion actually took place.
You may be familiar with Python decorators such as #lru_cache. It wraps any function and does MEMOIZATION of results improving the runtime:
#functools.lru_cache(maxsize=100)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
I want to build #lru_cache decorator in C++.
My implementation have one problem - when I wrap a recursive function and call it in a wrapping class, all subsequent recursive calls have no access to the cache. And as a result, I have 0 hits. Let me illustrate (I'll skip a bit of code).
LRUCache class:
template <typename Key, typename Val>
class LRUCache
{
public:
LRUCache( int capacity = 100 ) : capacity{ capacity } {}
Val get( Key key ) {... }
void put( Key key, Val value ) {... }
...
private:
int capacity;
std::list<std::pair<Val, Key>> CACHE;
std::unordered_map<Key, typename std::list<std::pair<Val, Key>>::iterator> LOOKUP;
};
_LruCacheFunctionWrapper class:
template <typename Key, typename Val>
class _LruCacheFunctionWrapper
{
struct CacheInfo {... };
public:
_LruCacheFunctionWrapper( std::function<Val( Key )> func, int maxSize )
: _wrapped{ func }
, _cache{ maxSize }
, _hits{ 0 }
, _misses{ 0 }
, _maxsize{ maxSize }
{}
template<typename... Args>
Val operator()( Args... args )
{
auto res = _cache.get( args... );
if( res == -1 )
{
++_misses;
res = _wrapped( args... );
_cache.put( args..., res );
}
else
++_hits;
return res;
}
CacheInfo getCacheInfo() {... }
void clearCache() {... }
private:
std::function<Val( Key )> _wrapped;
LRUCache<Key, Val> _cache;
int _hits;
int _misses;
int _maxsize;
};
And lastly, the target function:
long long fib( int n )
{
if( n < 2 )
return n;
return fib( n - 1 ) + fib( n - 2 );
}
You may see that the line:
res = _wrapped( args... );
is sending me into the function scope and I have to recalculate all recursive calls. How can I solve it?
Main.cpp:
_LruCacheFunctionWrapper<int, long long> wrapper( &fib, 50 );
for( auto i = 0; i < 16; ++i )
std::cout << wrapper( i ) << " ";
How can I declare a function that returns an std::optional lambda? e.g.
<what_do_i_put_here?> foo(bool b) {
if(b) return std::nullopt;
return [](int) { ... };
}
How about using the ternary operator? It will automatically deduce the correct optional type
#include <optional>
auto foo(bool b) {
return b ? std::nullopt : std::optional{[](int){}};
}
You can add a level of indirection to deduce the type via auto and decltype:
#include <optional>
auto foo_impl(){
return [](int){};
}
std::optional<decltype(foo_impl())> foo(bool b) {
if(b) return std::nullopt;
return foo_impl();
}
You can do it something like the following
#include <iostream>
#include <optional>
auto f( bool b )
{
auto l = [] { std::cout << "Hello World!"; };
std::optional<decltype( l )> opt;
if (b)
{
// some code
opt = l;
}
else
{
// some other cod
}
return opt;
}
int main()
{
( *f( true ) )( );
}
Another way is to use std::function with std::optional as for example
std::optional<std::function<void( int )>> g( bool b )
{
if (b)
{
return std::function<void( int )>( []( int x ) { std::cout << x; } );
}
else
{
return std::function<void( int )>( []( int x ) { std::cout << 2 * x; } );
}
}
In the upcoming C++23 you can avoid an extra function while only constructing your lambda in case it is needed. Unfortunately, support for this is currently experimental:
#include <optional>
auto foo(bool const b) {
return (b ? std::optional<bool>(true) : std::optional<bool>())
.transform([](bool){
return [](int){ return 42;};
});
}
(demo with gcc trunk)
This uses the new std::optional<T>::transform(F) member function.
I have the following problem:
template< typename Func >
class A
{
public:
A( Func f ) : _f( f ) {}
// ...
template< typename T_in = /*input type of _f */, typename T_out = /*output type of _f */ >
std::vector<T_out> operator()( const std::vector<T_in>& input)
{
std::vector<T_out> res( input.size() );
for( size_t i = 0 ; i < input.size() ; ++i )
res[ i ] = _f( input[ i ] );
return res;
}
private:
Func _f;
// ...
};
template< typename Func >
A<Func> A_wrapper( Func f )
{
return A<Func>( f );
}
int main()
{
// example for f(x) = x*x
std::vector<float> input = { /* ... */ };
auto f = []( float in ){ return in*in; };
auto map_square = A_wrapper( f );
auto res = map_square( input );
return 0;
}
As you can see above, I try to implement a class A whose function operator() maps a function _f to each element of an input vector input.
My problem is the following: I want the elements of the input vector input to have the input type of _f (i.e., T_in) and the elements of the output vector the output type of _f (i.e., T_out) but without passing the input/output type of _f explicitly to the class A, the function A_wrapper which I use for type deduction and/or the function operator() (due to a better readability of the code).
Has anyone an idea how the input/output type of _f can be deduced automatically at compile time?
Many thanks in advance.
BTW: The question here is related to my previous post Get input/output type of callable
Same question, same answer: you can deduce T_in from the input vector and T_out using std::result_of_t
#include <vector>
#include <functional>
template< typename Func >
class A
{
public:
A( Func f ) : _f( f ) {}
// ...
template< typename T_in,
typename T_out = std::result_of_t<Func(T_in)>>
std::vector<T_out> operator()( const std::vector<T_in> & input)
{
std::vector<T_out> res( input.size() );
for( size_t i = 0 ; i < input.size() ; ++i )
res[ i ] = _f( input[ i ] );
return res;
}
private:
Func _f;
// ...
};
template< typename Func >
A<Func> A_wrapper( Func f )
{
return A<Func>( f );
}
int main()
{
// example for f(x) = x*x
std::vector<float> input = { /* ... */ };
auto f = []( float in ){ return in*in; };
auto map_square = A_wrapper( f );
auto res = map_square( input );
return 0;
}
Using typename std::result_of<Func(T_in)>::type instead of std::result_of_t<Func(T_in)> should work also for C++11, not only for C++14.
I try to understand under what circumstances a C++ compiler is able to perform loop fusion and when not.
The following code measures the performance of two different ways to calculate the squared doubles (f(x) = (2*x)^2) of all values in a vector.
#include <chrono>
#include <iostream>
#include <numeric>
#include <vector>
constexpr int square( int x )
{
return x * x;
}
constexpr int times_two( int x )
{
return 2 * x;
}
// map ((^2) . (^2)) $ [1,2,3]
int manual_fusion( const std::vector<int>& xs )
{
std::vector<int> zs;
zs.reserve( xs.size() );
for ( int x : xs )
{
zs.push_back( square( times_two( x ) ) );
}
return zs[0];
}
// map (^2) . map (^2) $ [1,2,3]
int two_loops( const std::vector<int>& xs )
{
std::vector<int> ys;
ys.reserve( xs.size() );
for ( int x : xs )
{
ys.push_back( times_two( x ) );
}
std::vector<int> zs;
zs.reserve( ys.size() );
for ( int y : ys )
{
zs.push_back( square( y ) );
}
return zs[0];
}
template <typename F>
void test( F f )
{
const std::vector<int> xs( 100000000, 42 );
const auto start_time = std::chrono::high_resolution_clock::now();
const auto result = f( xs );
const auto end_time = std::chrono::high_resolution_clock::now();
const auto elapsed = end_time - start_time;
const auto elapsed_us = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
std::cout << elapsed_us / 1000 << " ms - " << result << std::endl;
}
int main()
{
test( manual_fusion );
test( two_loops );
}
The version with two loops takes about twice as much time as the version with one loop, even with -O3 for GCC and Clang.
Is there a way to allow the compiler to optimize two_loops into being as fast as manual_fusion without operating in-place in the second loop? The reason I'm asking is I want to make chained calls to my library FunctionalPlus like fplus::enumerate(fplus::transform(f, xs)); faster.
You can try modify your two_loops function as follows:
int two_loops( const std::vector<int>& xs )
{
std::vector<int> zs;
zs.reserve( xs.size() );
for ( int x : xs )
{
zs.push_back( times_two( x ) );
}
for ( int i=0 : i<zs.size(); i++ )
{
zs[i] = ( square( zs[i] ) );
}
return zs[0];
}
The point is to avoid allocating memory twice and push_back to another vector