Wenn ich ein kartesisches Produkt aus einer Liste von Listen in Haskell erstellen möchten, kann ich dies tun:Wie erstellt man eine Funktion, die einen kartesischen Produkt-Iterator von einem Iterator von Iteratoren erzeugt?
product [] = [[]]
product (xs:xss) = concatMap (\k -> map (k:) (product1 xss)) xs
oder sogar unter:
sequence xss
Ich versuche, eine effiziente Iterator zu implementieren das würde das gleiche tun in Rust, aber ich bin nicht sicher, was mit meinem Versuch, falsch ist:
use std::iter::{empty, once};
fn product<T, I, V>(xss: I) -> Box<Iterator<Item = Iterator<Item = T>>>
where
T: Clone,
V: IntoIterator<Item = T>,
I: IntoIterator<Item = V>,
{
Box::new(xss.into_iter().fold(once(empty()), |acc, xs| {
xs.into_iter().flat_map(|x| acc.map(|ys| ys.chain(once(x))))
}))
}
fn main() {
let data = vec![[1, 2, 3], [10, 20, 30], [100, 200, 300]];
let it: Vec<Vec<u32>> = product(data).collect();
println!("{:?}", it);
}
Erzeugt diese Fehler:
error[E0308]: mismatched types
--> src/main.rs:10:9
|
10 | xs.into_iter().flat_map(|x| acc.map(|ys| ys.chain(once(x))))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::iter::Once`, found struct `std::iter::FlatMap`
|
= note: expected type `std::iter::Once<std::iter::Empty<T>>`
found type `std::iter::FlatMap<<V as std::iter::IntoIterator>::IntoIter, std::iter::Map<std::iter::Once<std::iter::Empty<T>>, [[email protected]/main.rs:10:45: 10:67 x:_]>, [[email protected]/main.rs:10:33: 10:68 acc:_]>`
error[E0271]: type mismatch resolving `<std::iter::Once<std::iter::Empty<T>> as std::iter::Iterator>::Item == std::iter::Iterator<Item=T>`
--> src/main.rs:9:5
|
9 |/ Box::new(xss.into_iter().fold(once(empty()), |acc, xs| {
10 | | xs.into_iter().flat_map(|x| acc.map(|ys| ys.chain(once(x))))
11 | | }))
| |_______^ expected struct `std::iter::Empty`, found trait std::iter::Iterator
|
= note: expected type `std::iter::Empty<T>`
found type `std::iter::Iterator<Item=T>`
= note: required for the cast to the object type `std::iter::Iterator<Item=std::iter::Iterator<Item=T>>`
error[E0277]: the trait bound `[{integer}; 3]: std::iter::Iterator` is not satisfied
--> src/main.rs:16:29
|
16 | let it: Vec<Vec<u32>> = product(data).collect();
| ^^^^^^^ `[{integer}; 3]` is not an iterator; maybe try calling `.iter()` or a similar method
|
= help: the trait `std::iter::Iterator` is not implemented for `[{integer}; 3]`
= note: required because of the requirements on the impl of `std::iter::IntoIterator` for `[{integer}; 3]`
= note: required by `product`
error: the `collect` method cannot be invoked on a trait object
--> src/main.rs:16:43
|
16 | let it: Vec<Vec<u32>> = product(data).collect();
| ^^^^^^^
Der erste Fehler mir das Gefühl schenkt, dass Rust kann nicht einmal eine träge verbraucht Iterator mit fold
schaffen, weil Empty<T>
ein Iterator<Item = T>
ist (zumindest vom Konzept her), aber ich hoffe, ich bin falsch.
Boxed Iterator ist keine adäquate Substitution für lazy ausgewertete Haskell Variable, da sie nicht zurückgespult oder geklont werden kann und somit eine solche direkte Übersetzung nicht funktioniert. Die Darstellung einer Liste als Chain of Boxed 'Chain's wird auch nicht effizient sein. – red75prime
@ red75prime Okay, also wie mache ich das generisch und im funktionalen Stil? – user1685095
Du schreibst Rust, aber denkst Haskell, es wird schief gehen. Werfen Sie einen Blick auf [this] (http://killercup.github.io/vibrants-rs/itertools/struct.Product.html), um zu sehen, wie eine Rost-Implementierung aussehen könnte. – papagaga