针对不同类型参数共享相同特征的元素的funk折叠

时间:2018-12-07 16:56:03

标签: rust

我正在学习如何使用frunk in Rust

我对如何将foldl methodfolder参数用于具有相同类型特征且具有不同类型参数的元素提出疑问。我在下面写了一个带有foldl方法看似冗余的folder参数的示例(此示例编译得很好)。

是否有更简单的方法将static_forward函数传递给foldl

#[macro_use]
extern crate frunk;

trait Layer<InDim, OutDim> {
    fn forward(&self, input: Vec<InDim>) -> Vec<OutDim>;

    fn static_forward(input: Vec<InDim>, layer: &Self) -> Vec<OutDim> {
        layer.forward(input)
    }
}

struct FtoI {}
struct ItoF {}
struct FtoS {}

impl Layer<f32, i32> for FtoI {
    fn forward(&self, input: Vec<f32>) -> Vec<i32> {
        // In real case, converts the input to output.
        vec![1, 2, 3]
    }
}

impl Layer<i32, f32> for ItoF {
    fn forward(&self, input: Vec<i32>) -> Vec<f32> {
        // In real case, converts the input to output.
        vec![1., 2., 3.]
    }
}

impl Layer<f32, String> for FtoS {
    fn forward(&self, input: Vec<f32>) -> Vec<String> {
        // In real case, converts the input to output.
        vec![String::from("Hello"), String::from("world")]
    }
}

fn main() {
    let vec_float = vec![1., 2., 3.];
    # These elements share Layer trait with different type parameters
    let layers = hlist![FtoI {}, ItoF {}, FtoS {}];

    let r = layers.to_ref().foldl(
        hlist![
            // All of the element are same and seem redundant. Can this argument be simplified?
            Layer::static_forward,
            Layer::static_forward,
            Layer::static_forward
        ],
        vec_float,
    );
    /* This doesn't compile due to "type mismatch in function arguments "
    let r = layers.to_ref().foldl(Layer::static_forward, vec_float);
    */
    println!("result: {:?}", r);
}

1 个答案:

答案 0 :(得分:0)

从@ 1tgr得到了有关使用宏的想法。下面是我的实现。这需要为每个可能调用的“ N”手动定义“ @cons”部分,并在宏参数中指定“ 3”。

仍然在寻找更好的解决方案。

macro_rules! hcons_repeat {
    (@cons (0, $_e:expr))
        => { HNil };
    (@cons (1, $e:expr))
        => { HCons{ head: $e, tail: hcons_repeat!(@cons (0, $e))}};
    (@cons (2, $e:expr))
        => { HCons{ head: $e, tail: hcons_repeat!(@cons (1, $e))}};
    (@cons (3, $e:expr))
        => { HCons{ head: $e, tail: hcons_repeat!(@cons (2, $e))}};
    (@cons (4, $e:expr))
        => { HCons{ head: $e, tail: hcons_repeat!(@cons (3, $e))}};
    (@cons (5, $e:expr))
        => { HCons{ head: $e, tail: hcons_repeat!(@cons (4, $e))}};
    (@cons (6, $e:expr))
        => { HCons{ head: $e, tail: hcons_repeat!(@cons (5, $e))}};
    (@cons (7, $e:expr))
        => { HCons{ head: $e, tail: hcons_repeat!(@cons (6, $e))}};
    [$e:expr; $n:tt] => {
        {
            hcons_repeat!(@cons ($n, $e))
        }
    };
}

...

let r = layers
    .to_ref()
    .foldl(hcons_repeat![Layer::static_forward; 3], vec_float);