-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml6
-rw-r--r--src/lib.rs51
4 files changed, 65 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..e350587
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "bind"
+version = "0.1.0"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..b4eed99
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "bind"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..383bc90
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,51 @@
+#![feature(tuple_trait, unboxed_closures, fn_traits)]
+#![allow(private_bounds)]
+use core::ops::FnMut;
+use std::marker::Tuple;
+
+trait Head: Tuple {
+ type Head;
+ type Tail: Tuple;
+
+ fn rejoin(_: Self::Head, _: Self::Tail) -> Self;
+}
+
+macro_rules! impls {(
+ $($Hd:tt $($Tail:tt)*)?
+) => ($(impls!($($Tail)*);)?$(
+impl<$Hd $(, $Tail)*> Head for ($Hd, $($Tail),*) {
+ type Head = $Hd;
+ type Tail = ($($Tail, )*);
+ fn rejoin($Hd: Self::Head, tail: Self::Tail) -> Self {
+ let ($($Tail, )*) = tail;
+ ($Hd, $($Tail),*)
+ }
+})?)}
+impls![_13 _12 _11 _10 _9 _8 _7 _6 _5 _4 _3 _2 _1 _0];
+
+impl<Args: Head, F: FnMut<Args> + Sized> Bind<Args> for F {}
+pub trait Bind<Args: Head>: FnMut<Args> + Sized {
+ fn bind<T: Clone>(self, with: T) -> impl FnMut<Args::Tail, Output = Self::Output>
+ where
+ Args: Head<Head = T>,
+ {
+ return Fn { f: self, t: with };
+ struct Fn<Args: Head, F: FnMut<Args>> {
+ f: F,
+ t: Args::Head,
+ }
+ impl<Args: Head, F: FnMut<Args>> FnOnce<Args::Tail> for Fn<Args, F> {
+ type Output = F::Output;
+ extern "rust-call" fn call_once(mut self, args: Args::Tail) -> Self::Output {
+ let args = Args::rejoin(self.t, args);
+ self.f.call_mut(args)
+ }
+ }
+ impl<Args: Head<Head: Clone>, F: FnMut<Args>> FnMut<Args::Tail> for Fn<Args, F> {
+ extern "rust-call" fn call_mut(&mut self, args: Args::Tail) -> Self::Output {
+ let args = Args::rejoin(self.t.clone(), args);
+ self.f.call_mut(args)
+ }
+ }
+ }
+}