Created
January 24, 2020 23:12
-
-
Save jnape/a464d0895036a21144a7dd2e8551ec5b to your computer and use it in GitHub Desktop.
This file contains 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
#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