use core::marker::PhantomData; use crate::Node; pub struct ComposeNode Node<'i, I>, Second: for<'i> Node<'i, >::Output>, I> { first: First, second: Second, phantom: PhantomData, } impl<'i, Input: 'i, First, Second> Node<'i, Input> for ComposeNode where First: for<'a> Node<'a, Input> + 'i, Second: for<'a> Node<'a, >::Output> + 'i, { type Output = >::Output>>::Output; fn eval<'s: 'i>(&'s self, input: Input) -> Self::Output { let arg = self.first.eval(input); self.second.eval(arg) } } impl ComposeNode where First: for<'a> Node<'a, Input>, Second: for<'a> Node<'a, >::Output>, { pub const fn new(first: First, second: Second) -> Self { ComposeNode:: { first, second, phantom: PhantomData } } } // impl Clone for ComposeNode impl Clone for ComposeNode where First: for<'a> Node<'a, Input> + Clone, Second: for<'a> Node<'a, >::Output> + Clone, { fn clone(&self) -> Self { ComposeNode:: { first: self.first.clone(), second: self.second.clone(), phantom: PhantomData, } } } pub trait Then<'i, Input: 'i>: Sized { fn then(self, second: Second) -> ComposeNode where Self: for<'a> Node<'a, Input>, Second: for<'a> Node<'a, >::Output>, { ComposeNode::new(self, second) } } impl<'i, First: for<'a> Node<'a, Input>, Input: 'i> Then<'i, Input> for First {} pub struct ConsNode, Root>(pub Root, PhantomData); impl<'i, Root, Input: 'i, I: 'i + From<()>> Node<'i, Input> for ConsNode where Root: Node<'i, I>, { type Output = (Input, Root::Output); fn eval<'s: 'i>(&'s self, input: Input) -> Self::Output { let arg = self.0.eval(I::from(())); (input, arg) } } impl<'i, Root: Node<'i, I>, I: 'i + From<()>> ConsNode { pub fn new(root: Root) -> Self { ConsNode(root, PhantomData) } } #[cfg(test)] mod test { use crate::{ops::IdNode, value::ValueNode}; use super::*; #[test] fn compose() { let value = ValueNode::new(4u32); let compose = value.then(IdNode::new()); assert_eq!(compose.eval(()), &4u32); let type_erased = &compose as &dyn for<'i> Node<'i, (), Output = &'i u32>; assert_eq!(type_erased.eval(()), &4u32); } }