rust 匹配嵌套泛型类型

ljsrvy3e  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(141)

为了学习,我正在编写我自己的仿函数实现。从函数的Angular 来说,它没有意义,但它是学习语言如何工作以及如何用它实现更复杂结构的好方法。但我陷入了如何实现flatten函数的困境,我想采取可能的内部 Package 层并删除它。我的实现如下:

#[derive(Debug)]
enum Functor<T> {
  Functor(T),
}

type MapFn<T, S> = dyn Fn(T) -> S;

impl<T> Functor<T> {
    fn map<S>(self, operation: &MapFn<T, S>) -> Functor<S> {
      use Functor::Functor;

      match self {
          Functor(value) => Functor::<S>(operation(value))
      }
    }

    fn unwrap(self) -> T {
      use Functor::Functor;

      match self {
          Functor(value) => value
      }
    }

    fn flatten(self) -> Functor<T> {
      use Functor::Functor;

      // TODO: now just returns same instance
      // if the type inside is another functor, should "peel" one layer off,
      // otherwise if just value of <T>, should return self
      self
    }
}

字符串
但编译器确实理解 Package 的类型,例如,unwrap在以下代码中工作得很好

let fff = Functor(Functor(123));
println!("The value from wrapped functor is {:?}", fff.unwrap().unwrap())


我只是不知道如何实现它,以便编译器对这些类型感到满意。我试图从核心类型(如OptionResult)中查找类似的函子的源代码,但它们的操作不同。例如Option使用匹配来检查None
我在网上找到的解构 Package 类型的例子,往往有一个枚举内的结构,但在这里的类型是相同的,但不同的泛型参数,所以例如编译器不传递这样的东西

fn flatten(self) -> Functor<T> {
      use Functor::Functor;

      match self {
          Functor(Functor(T)) => ...,
      }
}


我得到的都是不匹配的类型。

qgelzfjb

qgelzfjb1#

对于Option类型,flatten函数是在Option<Option<T>>类型上实现的,所以对于你的自定义函子,你会有一个单独的impl块,像这样来表示这个方法只适用于内部类型为另一个FunctorFunctor

impl<T> Functor<Functor<T>> {
    fn flatten(self) -> Functor<T> {
        use Functor::Functor;
        match self {
            Functor(val) => val,
        }
    }
}

字符串
这告诉编译器内部类型也是Functor,所以它知道它可以解构为Functor(Functor(val))
这只允许一次展平一个层,这与Option类型相同。

相关问题