Как указать аргумент generi c для типа, который реализует черту Fn, когда аргументы не ограничены? - PullRequest
2 голосов
/ 09 марта 2020

Я пытаюсь реализовать черту, используя концепцию «карты». Я придумал следующий минимальный пример:

trait Value<T> {
    fn get(&self) -> T;
}
struct ValueMap<S, F> {
    s: S,
    f: F,
}
impl<T, U, S: Value<T>, F: Fn(T) -> U> Value<U> for ValueMap<S, F> {
    fn get(&self) -> U {
        (self.f)(self.s.get())
    }
}

Я получаю ошибку the type parameter T is not constrained by the impl trait, self type, or predicates.

Как мне реализовать черту Value для моего ValueMap struct когда F - это функция, которая отображает значение S на что-то еще?

Замечания: у меня нет этой проблемы, когда я использую связанные типы в Value. Но концепции все еще немного размыты для меня.

1 Ответ

2 голосов
/ 09 марта 2020

Подробности сообщения об ошибке # 0E207 говорят, что:

Любой параметр типа или параметр времени жизни impl должен соответствовать хотя бы одному из следующих критериев:

  • появляется в типе реализации impl, например, impl<T> Foo<T>
  • для черты impl, появляется в реализованной черте, например, impl<T> SomeTrait<T> for Foo
  • он связан как связанный тип, например impl<T, U> SomeTrait for T where T: AnotherTrait<AssocType=U>

Ничто из этого не относится к вашему T. То, что вы делаете, в настоящее время не поддерживается.

Это кажется хакерским, но я смог заставить это работать, добавив дополнительные параметры типа в ValueMap, опираясь на фантомных членов данных. Таким образом, каждый из типов встречается в типе реализации, и требования удовлетворяются.

trait Value<T> {
    fn get(&self) -> T;
}

struct ValueMap<T, U, S, F>
where
    F: Fn(T) -> U,
{
    s: S,
    f: F,
    _t: std::marker::PhantomData<T>,
    _u: std::marker::PhantomData<U>,
}

impl<T, U, S, F> Value<U> for ValueMap<T, U, S, F>
where
    S: Value<T>,
    F: Fn(T) -> U,
{
    fn get(&self) -> U {
        (self.f)(self.s.get())
    }
}

Playground link

...