#![feature(impl_trait_in_bindings, unboxed_closures, fn_traits)]
pub trait Map<A> {
type Output: Sequence;
fn apply(self, arg: A) -> Self::Output;
}
pub trait Fold<I, A> {
fn apply(self, init: I, arg: A) -> I;
}
pub trait Collection<A> {
fn apply(a: A) -> Self;
}
pub trait Zip<A> {
type Output: Sequence;
fn apply(self, a: A) -> Self::Output;
}
pub trait Sequence
where
Self: Sized,
{
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn map<F: Map<Self>>(self, f: F) -> F::Output {
f.apply(self)
}
fn fold<I, F: Fold<I, Self>>(self, init: I, f: F) -> I {
f.apply(init, self)
}
fn collect<C: Collection<Self>>(self) -> C {
C::apply(self)
}
fn zip<Z: Zip<Self>>(self, z: Z) -> Z::Output {
z.apply(self)
}
}
pub struct End;
pub struct Seq<A, B>(pub A, pub B);
impl Sequence for End {
fn len(&self) -> usize {
0
}
}
impl<A, B> Sequence for Seq<A, B>
where
B: Sequence,
{
fn len(&self) -> usize {
1 + self.1.len()
}
}
impl<F> Map<End> for F {
type Output = End;
fn apply(self, arg: End) -> Self::Output {
arg
}
}
impl<A, B, X, Y> Zip<Seq<X, Y>> for Seq<A, B>
where
B: Zip<Y>,
{
type Output = Seq<(X, A), B::Output>;
fn apply(self, Seq(x, y): Seq<X, Y>) -> Self::Output {
let Seq(a, b) = self;
Seq((x, a), b.apply(y))
}
}
impl Zip<End> for End {
type Output = End;
fn apply(self, _arg: End) -> Self::Output {
End
}
}
impl<F, A, B> Map<Seq<A, B>> for F
where
F: FnMut<(A,)>,
F: Map<B>,
{
type Output = Seq<<F as FnOnce<(A,)>>::Output, <F as Map<B>>::Output>;
fn apply(mut self, Seq(a, b): Seq<A, B>) -> Self::Output {
Seq(self(a), self.apply(b))
}
}
impl<F, I> Fold<I, End> for F {
fn apply(self, init: I, _arg: End) -> I {
init
}
}
impl<F, I, A, B> Fold<I, Seq<A, B>> for F
where
F: FnMut<(I, A), Output = I>,
F: Fold<I, B>,
{
fn apply(mut self, init: I, Seq(a, b): Seq<A, B>) -> I {
let next_init = self(init, a);
self.apply(next_init, b)
}
}
#[macro_export]
macro_rules! function {
(@switch) => {()};
(@switch $($tt:tt)+) => {$($tt)+};
($name:ident $(<$($generic: ident $(,)?)*>)? ($($($args:ident)+:$arg_ty: ty),* $(,)?) $(-> $ty:ty)? $(where ($($clauses:tt)*))? $body:block) => {
#[allow(non_camel_case_types)]
pub struct $name;
impl$(<$($generic,)*>)? FnOnce<($($arg_ty,)*)> for $name $(where $($clauses)*)? {
type Output = function!(@switch $($ty)?);
extern "rust-call" fn call_once(self, ($($($args)+,)*): ($($arg_ty,)*)) -> Self::Output {
$body
}
}
impl$(<$($generic,)*>)? FnMut<($($arg_ty,)*)> for $name $(where $($clauses)*)? {
extern "rust-call" fn call_mut(&mut self, ($($($args)+,)*): ($($arg_ty,)*)) -> Self::Output {
$body
}
}
impl$(<$($generic,)*>)? Fn<($($arg_ty,)*)> for $name $(where $($clauses)*)? {
extern "rust-call" fn call(&self, ($($($args)+,)*): ($($arg_ty,)*)) -> Self::Output {
$body
}
}
};
}
#[macro_export]
macro_rules! closure {
([$($capture:ident),* $(,)?] $(<$($generic: ident $(,)?)*>)? ($($($args:ident)+:$arg_ty: ty),* $(,)?) $(-> $ty:ty)? $(where ($($clauses:tt)*))? $body:block) => {{
pub struct Closure<$($capture,)*>($($capture)*);
impl<$($capture,)* $($($generic,)*)?> FnOnce<($($arg_ty,)*)> for Closure<$($capture,)*> $(where $($clauses)*)? {
type Output = function!(@switch $($ty)?);
extern "rust-call" fn call_once(self, ($($($args)+,)*): ($($arg_ty,)*)) -> Self::Output {
let Closure($($capture),*) = self;
$body
}
}
impl<$($capture,)* $($($generic,)*)?> FnMut<($($arg_ty,)*)> for Closure<$($capture,)*> $(where $($clauses)*)? {
extern "rust-call" fn call_mut(&mut self, ($($($args)+,)*): ($($arg_ty,)*)) -> Self::Output {
let Closure($(ref $capture),*) = *self;
$body
}
}
impl<$($capture,)* $($($generic,)*)?> Fn<($($arg_ty,)*)> for Closure<$($capture,)*> $(where $($clauses)*)? {
extern "rust-call" fn call(&self, ($($($args)+,)*): ($($arg_ty,)*)) -> Self::Output {
let Closure($(ref $capture),*) = *self;
$body
}
}
Closure($($capture),*)
}};
}
#[macro_export]
macro_rules! seq {
() => {
End
};
($expr:expr $(,)?) => {
Seq($expr, End)
};
($expr:expr, $($other:expr),+ $(,)?) => {
Seq($expr, seq!($($other,)+))
}
}
#[macro_export]
macro_rules! Seq {
() => {
End
};
($expr:ty $(,)?) => {
Seq<$expr, End>
};
($expr:ty, $($other:ty),+ $(,)?) => {
Seq<$expr, Seq!($($other),+)>
}
}
function!(fold_vector<T>(mut init: Vec<T>, val: T) -> Vec<T> {
init.push(val);
init
});
impl<T, B> Collection<Seq<T, B>> for Vec<T>
where
fold_vector: Fold<Vec<T>, Seq<T, B>>,
B: Sequence,
{
fn apply(a: Seq<T, B>) -> Self {
a.fold(Vec::new(), fold_vector)
}
}
function!(Dbg<T>(a: T) -> T where (T: std::fmt::Debug) {
println!("{:?}", a);
a
});
pub fn functor<F, T>(_: &F, _: &T)
where
F: Map<T>,
{
}
pub trait Struct {
type Fields: Sequence + Zip<Self::Names>;
type Names: Sequence + Zip<Self::Fields>;
fn fields(self) -> Self::Fields;
fn names() -> Self::Names;
}
pub struct Point {
pub x: i32,
pub y: &'static str,
pub z: i32,
}
impl Struct for Point {
type Fields = Seq!(i32, &'static str, i32);
type Names = Seq!(&'static str, &'static str, &'static str);
fn fields(self) -> Self::Fields {
seq!(self.x, self.y, self.z)
}
fn names() -> Self::Names {
seq!("x", "y", "z")
}
}
pub fn dbg<S: Struct>(s: S)
where
Dbg: Map<<<S as Struct>::Fields as Zip<<S as Struct>::Names>>::Output>,
{
let names: impl Sequence = S::names();
let fields: impl Sequence = s.fields();
names.zip(fields).map(Dbg);
}