Skip to content

Instantly share code, notes, and snippets.

@jnape
Created Jan 24, 2020
Embed
What would you like to do?
#include <thread>
#include <iostream>
#include <functional>
#include <algorithm>
#include <numeric>
#include <any>
namespace {
struct __ {};
struct ___ {};
struct ____ {};
}
template<typename A> using Id = A;
template<typename A> Id<A> pure(A a) { return a; }
template<typename A, typename B> Id<B> fmap(Id<A> id, std::function<B(A)> f) { return f(id); }
template<template<typename> typename F>
concept Functor = requires {
std::is_same_v<decltype(fmap(std::declval<F<__>>(), std::function<___(__)>())), F<___>>;
};
template<template<typename> typename F>
concept Pure = requires {
std::is_same_v<decltype(pure(std::declval<__>())), F<__>>;
};
template<template<typename> typename F>
concept Zip = requires {
std::is_same_v<decltype(zip(std::declval<F<__>>(), std::declval<F<std::function<___(__)>>>())), F<___>>;
};
template<template<typename> typename F>
concept FlatMap = requires {
std::is_same_v<decltype(ap(std::declval<F<__>>(), std::declval<std::function<F<___>(__)>>())), F<___>>;
};
template<template<typename> typename F>
concept Applicative = Pure<F> && Zip<F>;
template<template<typename> typename F>
concept Monad = Applicative<F> && FlatMap<F>;
template<template<typename, typename> typename Coproduct>
concept Match = requires {
std::is_same_v<decltype(match(std::declval<Coproduct<__, ___>>(), std::declval<std::function<____(__)>>(), std::declval<std::function<____(___)>>())), ____>;
};
template<template<typename> typename F>
requires Functor<F>
F<int> inc(F<int> f) {
return fmap<int, int>(f, [](int x){ return x + 1;});
}
template<template<typename, typename> typename Coproduct>
requires Match<Coproduct>
int toS(Coproduct<std::string, int> strOrInt) {
return match(strOrInt, [](auto x) { return x; }, [](int x) { return std::to_string(x); });
}
namespace Either {
template<template<typename, typename> typename Coproduct, typename L, typename R>
requires Match<Coproduct>
using Mu = Coproduct<L, R>;
template<typename L, typename R>
struct Left {
L l;
public:
Left(L v) : l(v) {};
};
template<typename L, typename R>
struct Right {
R r;
public:
Right(R v) : r(v) {};
};
template<typename L, typename R, typename X>
X match(Left<L, R> left, std::function<X(L)> lFn, std::function<X(R)> rFn) {
return lFn(left.l);
}
template<typename L, typename R, typename X>
X match(Right<L, R> right, std::function<X(L)> lFn, std::function<X(R)> rFn) {
return rFn(right.r);
}
template<typename L, typename R>
Left<L, R> left(L l) {
return Left<L, R>(l);
}
template<typename L, typename R>
Right<L, R> right(R r) {
return Right<L, R>(r);
}
}
int main() {
Id<int> f = 42;
fmap<int,int>(f, [](int x) { return x + 1; });
inc<Id>(f);
auto e = Either::left<std::string, int>("asdf");
int r = match<std::string, int, int>(e, [](auto) { return -1; }, [](int x) { return x; });
std::cout << "compiled: " << std::to_string(r) << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment