-
-
Save rust-play/39bffcf6f0374b1a6722d41b50986d9c to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
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
/// Warning: the following code is made for experiment. | |
/// If you cause losses due to the use of this code in production, I am not responsible. | |
#[derive(PartialEq, Eq, Clone, Debug)] | |
pub struct List<T = ()>(pub Vec<T>); | |
#[derive(PartialEq, Eq, Clone, Debug)] | |
pub struct Id<T = ()>(pub T); | |
pub trait HKT<T> { | |
type Actual; | |
} | |
pub type Apply<H, T> = <H as HKT<T>>::Actual; | |
impl<T> HKT<T> for List { | |
type Actual = List<T>; | |
} | |
impl<T> HKT<T> for Id { | |
type Actual = Id<T>; | |
} | |
pub trait Monad<T>: HKT<T> { | |
fn ret(value: T) -> Apply<Self, T>; | |
fn bind<R>(value: Apply<Self, T>, f: &dyn Fn(T) -> Apply<Self, R>) -> Apply<Self, R> | |
where | |
Self: HKT<R>; | |
} | |
impl List { | |
fn bind_impl<T, R>(value: Apply<Self, T>, f: &dyn Fn(T) -> Apply<Self, R>) -> Apply<Self, R> { | |
let mut result = vec![]; | |
for v in value.0.into_iter() { | |
for v in f(v).0.into_iter() { | |
result.push(v); | |
} | |
} | |
List(result) | |
} | |
} | |
impl<T: Clone> Monad<T> for List { | |
fn ret(value: T) -> Apply<Self, T> { | |
List(vec![value]) | |
} | |
/// The bind method cannot be directly implemented due to a weird compilation error. | |
fn bind<R>(value: Apply<Self, T>, f: &dyn Fn(T) -> Apply<Self, R>) -> Apply<Self, R> | |
where | |
Self: HKT<R>, | |
{ | |
Self::bind_impl::<T, R>(value, f) | |
} | |
} | |
impl Id { | |
fn bind_impl<T, R>(value: Apply<Self, T>, f: &dyn Fn(T) -> Apply<Self, R>) -> Apply<Self, R> { | |
f(value.0) | |
} | |
} | |
impl<T> Monad<T> for Id { | |
fn ret(value: T) -> Apply<Self, T> { | |
Id(value) | |
} | |
fn bind<R>(value: Apply<Self, T>, f: &dyn Fn(T) -> Apply<Self, R>) -> Apply<Self, R> | |
where | |
Self: HKT<R>, | |
{ | |
Self::bind_impl::<T, R>(value, f) | |
} | |
} | |
pub fn lift2<T: Clone, R, H: Monad<T> + Monad<R> + Monad<(T, R)>>( | |
v1: Apply<H, T>, | |
v2: Apply<H, R>, | |
) -> Apply<H, (T, R)> | |
where | |
Apply<H, R>: Clone, | |
{ | |
<H as Monad<T>>::bind::<(T, R)>(v1, &|v1| { | |
<H as Monad<R>>::bind::<(T, R)>(v2.clone(), &|v2| { | |
<H as Monad<(T, R)>>::ret((v1.clone(), v2)) | |
}) | |
}) | |
} | |
fn main() { | |
assert_eq!(lift2::<_, _, Id>(Id(0), Id("")), Id((0, ""))); | |
assert_eq!( | |
lift2::<_, _, List>(List(vec![0, 1, 2]), List(vec!["", "1", "2"])), | |
List(vec![ | |
(0, ""), | |
(0, "1"), | |
(0, "2"), | |
(1, ""), | |
(1, "1"), | |
(1, "2"), | |
(2, ""), | |
(2, "1"), | |
(2, "2") | |
]) | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment