use std::future::Future;
use std::pin::Pin;
use crate::effect::writer::WriterEffect;
use crate::effect::Effect;
use crate::Monoid;
type BoxedWriterFn<T, E, Env, W> = Box<
dyn FnOnce(Env) -> Pin<Box<dyn Future<Output = (Result<T, E>, W)> + Send + 'static>>
+ Send
+ 'static,
>;
pub struct BoxedWriterEffect<T, E, Env, W>
where
Env: Clone + Send + Sync + 'static,
W: Monoid + Send + 'static,
{
inner: BoxedWriterFn<T, E, Env, W>,
}
impl<T, E, Env, W> std::fmt::Debug for BoxedWriterEffect<T, E, Env, W>
where
Env: Clone + Send + Sync + 'static,
W: Monoid + Send + 'static,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BoxedWriterEffect").finish_non_exhaustive()
}
}
impl<T, E, Env, W> BoxedWriterEffect<T, E, Env, W>
where
T: Send + 'static,
E: Send + 'static,
Env: Clone + Send + Sync + 'static,
W: Monoid + Send + 'static,
{
pub fn new<Eff>(effect: Eff) -> Self
where
Eff: WriterEffect<Output = T, Error = E, Env = Env, Writes = W> + Send + 'static,
{
BoxedWriterEffect {
inner: Box::new(move |env: Env| Box::pin(async move { effect.run_writer(&env).await })),
}
}
}
impl<T, E, Env, W> Effect for BoxedWriterEffect<T, E, Env, W>
where
T: Send + 'static,
E: Send + 'static,
Env: Clone + Send + Sync + 'static,
W: Monoid + Send + 'static,
{
type Output = T;
type Error = E;
type Env = Env;
async fn run(self, env: &Self::Env) -> Result<Self::Output, Self::Error> {
let (result, _writes) = (self.inner)(env.clone()).await;
result
}
}
impl<T, E, Env, W> WriterEffect for BoxedWriterEffect<T, E, Env, W>
where
T: Send + 'static,
E: Send + 'static,
Env: Clone + Send + Sync + 'static,
W: Monoid + Send + 'static,
{
type Writes = W;
async fn run_writer(
self,
env: &Self::Env,
) -> (Result<Self::Output, Self::Error>, Self::Writes) {
(self.inner)(env.clone()).await
}
}