Frunk Foldl против элементов, которые имеют одинаковую черту с различными параметрами типа - PullRequest
0 голосов
/ 07 декабря 2018

Я учусь использовать frunk в Rust .

У меня вопрос о том, как использовать аргумент folder метода foldl против элементов, которые имеют одинаковую черту с параметрами другого типа .Ниже я написал пример с кажущимся избыточным параметром folder (этот пример прекрасно компилируется) метода foldl.

Есть ли более простой способ передать функцию 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 голосов
/ 08 декабря 2018

Получил представление от @ 1tgr об использовании макроса.Ниже моя реализация.Это требует ручного определения части '@cons' для каждого 'N', который может быть вызван, и указания «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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...