Skip to content

Instantly share code, notes, and snippets.

@okkero
Created February 11, 2018 21:50
Show Gist options
  • Save okkero/c60c6dce96a6b304b113cb7726857305 to your computer and use it in GitHub Desktop.
Save okkero/c60c6dce96a6b304b113cb7726857305 to your computer and use it in GitHub Desktop.
C++ HKT
#include <iostream>
#include <functional>
#include <optional>
template<template<typename> typename F>
struct Functor
{
template<typename A, typename B>
static F<B> map(const F<A> &, const std::function<B (const A &)> &);
};
template<template<typename> typename F>
struct Applicative
{
template<typename A>
static F<A> pure(A);
template<typename A, typename B>
static F<B> apply(const F<A> &, const F<const std::function<B (const A &)> &> &);
};
template<template<typename> typename M>
struct Monad
{
template<typename A, typename B>
static M<B> bind(const M<A> &, const std::function<M<B> (const A &)> &);
};
template<>
struct Functor<std::optional>
{
template<typename A, typename B>
static std::optional<B> map(std::optional<A> &o, const std::function<B (const A &)> &f)
{
if (o)
{
return f(*o);
}
else
{
return {};
}
}
};
template<>
struct Applicative<std::optional>
{
template<typename A>
static std::optional<A> pure(A a)
{
return a;
}
template<typename A, typename B>
static std::optional<B> apply(const std::optional<A> &o, const std::optional<const std::function<B (A &)> &> &f)
{
if (o && f)
{
return f(*o);
}
else
{
return {};
}
}
};
template<>
struct Monad<std::optional>
{
template<typename A, typename B>
static std::optional<B> bind(const std::optional<A> &o, const std::function<std::optional<B> (const A &)> &f)
{
if (o)
{
return f(*o);
}
else
{
return {};
}
}
};
template<template<typename> typename M, typename A, typename B, typename C>
M<C> map2(const M<A> &a, const M<B> &b, const std::function<C (const A &, const B &)> &f)
{
return Monad<M>::template bind<A, C>(a, [&](const A &a_value) {
return Monad<M>::template bind<B, C>(b, [&](const B &b_value) {
return Applicative<M>::template pure(f(a_value, b_value));
});
});
}
template<typename T>
void print_optional(const std::optional<T> &o)
{
if (o)
{
std::cout << "Some(" << *o << ")" << std::endl;
}
else
{
std::cout << "None" << std::endl;
}
}
int main(int argc, char **argv)
{
std::optional<int> a = 3;
std::optional<int> b = 6;
std::optional<int> c = {};
auto multiply = [](const int &a, const int &b) { return a * b; };
std::optional<int> r1 = map2<std::optional, int, int, int>(a, b, multiply);
std::optional<int> r2 = map2<std::optional, int, int, int>(a, c, multiply);
std::optional<int> r3 = map2<std::optional, int, int, int>(b, c, multiply);
print_optional(r1);
print_optional(r2);
print_optional(r3);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment