From cfff85b6ca9b756a0fa8eec16403aff9604fdd49 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Tue, 28 Feb 2023 12:44:40 +0000 Subject: [PATCH 1/2] Implement applyl_at and applyr_at functions --- core/src/lib.rs | 2 ++ core/src/utils.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 core/src/utils.rs diff --git a/core/src/lib.rs b/core/src/lib.rs index bc16035f..dafed617 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -73,5 +73,7 @@ pub mod path; pub mod traits; mod tuples; +pub mod utils; + #[cfg(test)] mod test_structs; diff --git a/core/src/utils.rs b/core/src/utils.rs new file mode 100644 index 00000000..15d0b158 --- /dev/null +++ b/core/src/utils.rs @@ -0,0 +1,82 @@ +use core::marker::PhantomData; + +use crate::{ + hlist::{HFoldRightable, HList}, + traits::{Func, Poly}, +}; + +pub struct ApplyN(PhantomData); +type ApplyNAcc = (Option, usize, usize); // targetN, currN, R + +impl Func<(ApplyNAcc<>::Output>, S)> for ApplyN +where + F: Func, +{ + type Output = ApplyNAcc<>::Output>; + + fn call(((r, tgt_n, curr_n), s): (ApplyNAcc<>::Output>, S)) -> Self::Output { + if tgt_n == curr_n { + (Some(F::call(s)), tgt_n, curr_n + 1) + } else { + (r, tgt_n, curr_n + 1) + } + } +} + +pub fn applyr_at(hl: T, n: usize, _: F) -> Option +where + T: HFoldRightable>, ApplyNAcc, Output = ApplyNAcc> + HList, +{ + let len = hl.len(); + if n >= len { + return None; + } + let (r, _, _) = hl.foldr(Poly(ApplyN::(PhantomData)), (None, n, 0)); + r +} + +pub fn applyl_at(hl: T, n: usize, f: F) -> Option +where + T: HFoldRightable>, ApplyNAcc, Output = ApplyNAcc> + HList, +{ + let len = hl.len(); + if n >= len { + return None; + } + applyr_at(hl, len - n - 1, f) +} + +#[cfg(test)] +mod tests { + use super::*; + + struct IsDefault; + impl Func for IsDefault + where + T: Default + PartialEq, + { + type Output = bool; + + fn call(i: T) -> Self::Output { + let r = T::default() == i; + r + } + } + + #[test] + fn test_apply() { + let lst = hlist![10u32, "xyz", 0usize]; + + assert_eq!(applyr_at(lst.clone(), 0, IsDefault).unwrap(), true); + assert_eq!(applyr_at(lst.clone(), 1, IsDefault).unwrap(), false); + assert_eq!(applyr_at(lst.clone(), 2, IsDefault).unwrap(), false); + + // Couldn't figure out how to create Func impl for references :( + // assert_eq!(applyr_at(lst.clone().to_ref(), 1, IsDefault).unwrap(), false); + // assert_eq!(applyr_at(lst.clone().to_mut(), 2, IsDefault).unwrap(), false); + + assert_eq!(applyl_at(lst.clone(), 0, IsDefault).unwrap(), false); + assert_eq!(applyl_at(lst.clone(), 1, IsDefault).unwrap(), false); + assert_eq!(applyl_at(lst.clone(), 2, IsDefault).unwrap(), true); + } +} From af879fc410b48f43ac11770e608047111e163f8e Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Wed, 1 Mar 2023 02:20:52 +0000 Subject: [PATCH 2/2] Introduce apply variant with arguments --- core/src/utils.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/core/src/utils.rs b/core/src/utils.rs index 15d0b158..fadc9304 100644 --- a/core/src/utils.rs +++ b/core/src/utils.rs @@ -6,8 +6,8 @@ use crate::{ }; pub struct ApplyN(PhantomData); -type ApplyNAcc = (Option, usize, usize); // targetN, currN, R +type ApplyNAcc = (Option, usize, usize); // R, targetN, currN impl Func<(ApplyNAcc<>::Output>, S)> for ApplyN where F: Func, @@ -23,6 +23,23 @@ where } } +type ApplyNArgsAcc = (Option, FA, usize, usize); // R, FArgs, targetN, currN +impl Func<(ApplyNArgsAcc<>::Output,FA>, S)> for ApplyN +where + F: Func<(FA,S)>, + FA: Copy +{ + type Output = ApplyNArgsAcc<>::Output, FA>; + + fn call(((r, args, tgt_n, curr_n), s): (ApplyNArgsAcc<>::Output,FA>, S)) -> Self::Output { + if tgt_n == curr_n { + (Some(F::call((args, s))), args, tgt_n, curr_n + 1) + } else { + (r, args, tgt_n, curr_n + 1) + } + } +} + pub fn applyr_at(hl: T, n: usize, _: F) -> Option where T: HFoldRightable>, ApplyNAcc, Output = ApplyNAcc> + HList, @@ -35,6 +52,18 @@ where r } +pub fn applyr_args_at(hl: T, n: usize, _: F, args: FA) -> Option +where + T: HFoldRightable>, ApplyNArgsAcc, Output = ApplyNArgsAcc> + HList, +{ + let len = hl.len(); + if n >= len { + return None; + } + let (r,_ , _, _) = hl.foldr(Poly(ApplyN::(PhantomData)), (None, args, n, 0)); + r +} + pub fn applyl_at(hl: T, n: usize, f: F) -> Option where T: HFoldRightable>, ApplyNAcc, Output = ApplyNAcc> + HList, @@ -46,6 +75,17 @@ where applyr_at(hl, len - n - 1, f) } +pub fn applyl_args_at(hl: T, n: usize, f: F, args: FA) -> Option +where + T: HFoldRightable>, ApplyNArgsAcc, Output = ApplyNArgsAcc> + HList, +{ + let len = hl.len(); + if n >= len { + return None; + } + applyr_args_at(hl, len - n - 1, f, args) +} + #[cfg(test)] mod tests { use super::*; @@ -79,4 +119,29 @@ mod tests { assert_eq!(applyl_at(lst.clone(), 1, IsDefault).unwrap(), false); assert_eq!(applyl_at(lst.clone(), 2, IsDefault).unwrap(), true); } + + struct FomatPrefix; + impl Func<(&str,T)> for FomatPrefix + where T: std::fmt::Display + { + type Output = String; + + fn call((args,i): (&str, T)) -> Self::Output { + let prefix = args; + format!("{}: {}", prefix, i) + } + } + + #[test] + fn test_apply_args() { + let lst = hlist![10u32, "xyz", 0usize]; + + assert_eq!(&applyr_args_at(lst.clone(), 0, FomatPrefix, "usize").unwrap(), "usize: 0"); + assert_eq!(&applyr_args_at(lst.clone(), 1, FomatPrefix, "str").unwrap(), "str: xyz"); + assert_eq!(&applyr_args_at(lst.clone(), 2, FomatPrefix, "u32").unwrap(), "u32: 10"); + + assert_eq!(&applyl_args_at(lst.clone(), 0, FomatPrefix, "u32").unwrap(), "u32: 10"); + assert_eq!(&applyl_args_at(lst.clone(), 1, FomatPrefix, "str").unwrap(), "str: xyz"); + assert_eq!(&applyl_args_at(lst.clone(), 2, FomatPrefix, "usize").unwrap(), "usize: 0"); + } }