#ifndef FWDLIB_HPP
#define FWDLIB_HPP

#include <string>
#include <optional>
#include <iostream>
#include <functional>
#include <unordered_map>
#include <unordered_set>

using namespace std;

typedef const char *fwd_err_t;

static fwd_err_t fwd_getline(auto next)
{
	if (cin.eof())
		return next(optional<string>{});

	if (string line; getline(cin, line))
		return next(optional<string>{line});
	else
		return next(optional<string>{});
}

static fwd_err_t fwd_foreach(auto container, auto next)
{
	for (auto &n : container)
		if (auto e = next(n))
			return e;

	return nullptr;
}

static fwd_err_t fwd_some(auto option, auto ok, auto fail)
{
	if (option)
		return ok(std::move(option.value()));
	else
		return fail();
}

static fwd_err_t fwd_copy(auto n, auto next)
{
	return next(n, n);
}

static fwd_err_t fwd_null(auto *x, auto fail, auto ok)
{
	if (x)
		return ok(*x);
	else
		return fail();
}

static fwd_err_t fwd_insert(auto container, auto elem, auto next)
{
	container.insert(std::move(elem));
	return next(std::move(container));
}

static fwd_err_t fwd_println(auto elem)
{
	cout << elem << endl;
	return nullptr;
}

static fwd_err_t fwd_intalloc(auto ok)
{
	int *p = new int{20};
	return ok(p);
}

static fwd_err_t fwd_destroy(auto /* a */)
{
	/* RAII destroys a */
	return nullptr;
}

#endif /* FWDLIB_HPP */