lloydmeta / frunk

Funktional generic type-level programming in Rust: HList, Coproduct, Generic, LabelledGeneric, Validated, Monoid and friends.
https://beachape.com/frunk/
MIT License
1.29k stars 58 forks source link

Allow folding hlist with a single `Poly` #170

Closed ImmemorConsultrixContrarie closed 3 years ago

ImmemorConsultrixContrarie commented 3 years ago

Added a mention of Poly in docs, added implementations for both foldl and foldr, added simple tests.

Where it could be usable:

  1. Folding a hlist of hlists with a single Poly.
  2. Inversing a map -> chain iterator dependency (especially useful for by-value iterators mixed with by-ref iterators, where you don't want to clone referenced values):
use frunk_core::{
    traits::{Func, Poly},
    *,
};
use std::borrow::Borrow;

struct Sum;
impl<I, T> Func<(i32, I)> for Sum
where
    I: IntoIterator<Item = T>,
    T: Borrow<i32>,
{
    type Output = i32;

    fn call(args: (i32, I)) -> i32 {
        let (acc, iter) = args;
        iter.into_iter().fold(acc, |acc, x| acc + *x.borrow())
    }
}

fn main() {
    // Can do this:
    let h = hlist![0..10, [1, 2, 3, 4].iter()];
    let res = h.foldl(Poly(Sum), 0);

    // Can't do this:
    // let sum: i32 = (0..10).map(|x| x.borrow()).chain([1, 2, 3, 4].iter()).sum();
    //                                -^^^^^^^^^
    //                                |
    //                                returns a value referencing data owned by the current function
    //                                `x` is borrowed here
}
  1. Probably more use cases I haven't thought of.
ExpHP commented 3 years ago

poke

I just randomly remembered this exists out of the blue. Do we want to merge?

lloydmeta commented 3 years ago

Yep we do want to merge this; I've just kept it open for now because I don't have time yet to merge and release. 🙇‍♂️