为了学习,我正在编写我自己的仿函数实现。从函数的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())
型
我只是不知道如何实现它,以便编译器对这些类型感到满意。我试图从核心类型(如Option
和Result
)中查找类似的函子的源代码,但它们的操作不同。例如Option
使用匹配来检查None
。
我在网上找到的解构 Package 类型的例子,往往有一个枚举内的结构,但在这里的类型是相同的,但不同的泛型参数,所以例如编译器不传递这样的东西
fn flatten(self) -> Functor<T> {
use Functor::Functor;
match self {
Functor(Functor(T)) => ...,
}
}
型
我得到的都是不匹配的类型。
1条答案
按热度按时间qgelzfjb1#
对于
Option
类型,flatten
函数是在Option<Option<T>>
类型上实现的,所以对于你的自定义函子,你会有一个单独的impl
块,像这样来表示这个方法只适用于内部类型为另一个Functor
的Functor
:字符串
这告诉编译器内部类型也是
Functor
,所以它知道它可以解构为Functor(Functor(val))
。这只允许一次展平一个层,这与
Option
类型相同。