Skip to content

Instantly share code, notes, and snippets.

@ClarkeRemy
Created April 2, 2024 08:55
Show Gist options
  • Save ClarkeRemy/3a794f7dc23be0586b1142a66e3151bc to your computer and use it in GitHub Desktop.
Save ClarkeRemy/3a794f7dc23be0586b1142a66e3151bc to your computer and use it in GitHub Desktop.
Bad Transducers
use std::{sync::Arc};
#[derive(PartialEq, Eq,Debug, PartialOrd, Ord)]
enum Reduced<A>{
Continue(A),
Reduced(A)
}
#[derive(Clone)]
enum List<T>{
Nil,
Cons(Arc<(T,List<T>)>)
}
macro_rules! list {
() => {
List::Nil
};
($VAL:expr) => {
List::Cons(Arc::new(($VAL,List::Nil)))
};
($VAL:expr, $($VALS:expr),+ $(,)?) => {
List::Cons(Arc::new(($VAL,list![$($VALS),+])))
}
}
type __<In,Out> = Arc<dyn Fn(In)->Out + 'static>;
fn ___<In,Out>(f : impl Fn(In)->Out + 'static)->__<In,Out>{
Arc::new(f)
}
// (b -> a -> b) -> b -> [a] -> b
fn reduce_v1<A,B>()->
__<
__<B,__<A,Reduced<B>>>
, __<B
, __<List<A>
, B
>>>
where
A : Clone + 'static,
B : Clone + 'static,
{
___(move|f : __<B,__<A,Reduced<B>>>|{
___(move|z : B| { let f = f.clone();
___(move|l : List<A>| { let z = z.clone();
match l.clone() {
List::Nil => z,
List::Cons(c)=> {
let (x,xs) = (*c).clone();
match f(z)(x) {
Reduced::Reduced( res) => res,
Reduced::Continue( res) => reduce_v1()(f.clone())(res)(xs)
}
}
}
})})})
}
#[derive(Clone)]
struct Reducer<S,A,B> {
init_state : S,
complete : __<S,__<B, B>>,
step : __<S,__<B, __<A, (S, Reduced<B>)>>>
}
fn reduce<S,A,B>()
->__<Reducer<S,A,B>
, __<B
, __<List<A>
, B>>>
where
S : Clone + 'static,
A : Clone + 'static,
B : Clone + 'static,
{
return
___(move|r:Reducer<S,A,B>|
___(move|z:B| { let r = r.clone();
___(move|a_list|{ let Reducer { init_state, complete, step } = r.clone();
let (state, res) = reduce_()(step)(init_state)(z.clone())(a_list);
complete(state)(res)
})}));
// where ...
fn reduce_<S,A,B>()
->__< __<S
, __<B
, __<A
, (S, Reduced<B>)>>>
, __<S
, __<B
, __<List<A>
, (S,B)
>>>>
where
S : Clone + 'static,
A : Clone + 'static,
B : Clone + 'static,
{
___(move|f: __<S, __<B, __<A, (S, Reduced<B>)>>>|
___(move|state:S| { let f = f.clone();
___(move|acc:B| { let (state, f) = (state.clone(), f.clone());
___(move|list:List<A>|{ let (state,acc,f) = (state.clone(),acc.clone(),f.clone());
match list {
List::Nil => (state,acc),
List::Cons(cons) => {
let (head,tail) = (*cons).clone();
match f(state)(acc)(head) {
(s, Reduced::Reduced(v)) => (s, v),
(s, Reduced::Continue(v)) => reduce_()(f)(s)(v)(tail)
}
}
}
})})}))
}
}
fn stateless<A,B>()
->__<__<B
,__<A,
B
>>
, Reducer<(), A, B>
>
where
A : Clone + 'static,
B : Clone + 'static,
{
___(move|f : __<B,__<A,B>>|{
let f = f.clone();
Reducer
{ init_state : ()
, complete : ___(move|_|
___(move|x|x
))
, step : ___(move|_| { let f = f.clone();
___(move|x : B| { let (x,f)= (x.clone(), f.clone());
___(move|y : A| { let (x,f)= (x.clone(), f.clone());
((), Reduced::Continue(f(x)(y)))
})})})
}
})
}
fn filtering_v1<S,A,B>()
->__<__<A,bool>
, __<Reducer<S,A,B>
, Reducer<S,A,B>>>
where
S : Clone + 'static,
A : Clone + 'static,
B : Clone + 'static,
{
return
___(move|pred : __<A,bool>|
___(move|r : Reducer<S,A,B>| {
let (pred, Reducer { init_state, complete, step }) = (pred.clone(),r.clone());
let filter_step = ___(move|s: S| { let (step,pred) = (step.clone(), pred.clone());
___(move|acc:B| { let (step,pred,s) = (step.clone(), pred.clone(),s.clone());
___(move|x:A| { let (step,pred,s,acc) = (step.clone(), pred.clone(),s.clone(),acc.clone());
if pred(x.clone()) { step(s)(acc)(x) }
else { (s, Reduced::Continue(acc)) }
})})});
Reducer {
init_state,
complete,
step : filter_step,
}
}))
}
fn filtering<S,A,B>()
->__<__<A,bool>
, __<Reducer<S,A,B>
, Reducer<((),S),A,B>>>
where
S : Clone + 'static,
A : Clone + 'static,
B : Clone + 'static,
{
return
___(move|pred : __<A,bool>|
___(move|r : Reducer<S,A,B>| {
let (pred, Reducer { init_state, complete, step }) = (pred.clone(),r.clone());
let filter_step = ___(move|s: ((), S)| { let (step,pred) = (step.clone(), pred.clone());
___(move|acc:B| { let (step,pred,s) = (step.clone(), pred.clone(),s.clone());
___(move|x:A| { let (step,pred,s,acc) = (step.clone(), pred.clone(),s.clone(),acc.clone());
let (my_state, s) = s;
if pred(x.clone()) {
let (s_, res) = step(s)(acc)(x);
((my_state, s_), res)
}
else { ((my_state, s), Reduced::Continue(acc)) }
})})});
Reducer {
init_state : ((), init_state),
complete : ___(move|x : ((),S)| complete(x.1)),
step : filter_step,
}
}))
}
fn main() {
let rplus = ___(move|a|___(move|b| Reduced::Continue(a+b)));
println!("{}", reduce_v1()(rplus)(0)(list!(1,2,3)));
let take_first = ___(move|a|___(move|_b|Reduced::Reduced(a)));
println!("{}", reduce_v1()(take_first)(42)(list!(1,2,3)));
let rplus = Reducer
{ init_state : ()
, complete : ___(move|_s|___(move|b:i32|b.clone()))
, step :
___(move|s|
___(move|b|
___(move|a| (s, Reduced::Continue(b + a))
)))
};
println!("{}", reduce()(rplus)(0)(list!(1,2,3)));
println!("{}",
reduce()
(stateless()(___(move|x|
___(move|y| x + y))))
(0)
(list!(1,2,3))
);
println!("{}",
reduce()
( filtering_v1()
(___(move|a|a%2 == 0))
(stateless()(___(move|x|
___(move|y| x + y)))))
(0)
(list!(1,2,3,4,5,6))
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment