Rust中Identity<A>与Option<_>的Monad trait实现冲突问题
问题原因与解决办法
冲突根源
Rust中的type是类型别名,并非创建新类型。你定义的type Identity<A> = A意味着Identity<X>和X是完全等价的同一类型,没有任何区别。
所以你的impl<X> Monad for Identity<X>本质上等同于:
impl<X> Monad for X { // 实现代码 }
这是一个给所有类型都实现Monad的全局实现,必然会和你之前为Option<X>编写的专属实现冲突——因为Option<X>同时匹配这两个impl,Rust无法确定该选用哪一个。
解决办法:使用新类型模式(Newtype Pattern)
要实现真正独立的Identity Monad,不能用类型别名,需要通过结构体创建一个全新的包装类型:
// 用结构体包裹原类型,创建新类型 #[derive(Debug, Clone, Copy)] pub struct Identity<A>(pub A); // 为这个新类型实现Monad trait impl<A> Monad for Identity<A> { // 示例:假设Monad包含flat_map方法 fn flat_map<B, F>(self, f: F) -> Identity<B> where F: FnOnce(A) -> Identity<B>, { f(self.0) } }
新类型模式是Rust中模拟包装类型的常用技巧,不会带来额外运行时开销,同时能让你为这个包装后的类型单独实现trait,完全避免和其他类型的实现冲突。
如果需要让Identity像原类型一样被直接访问,还可以实现Deref trait:
use std::ops::Deref; impl<A> Deref for Identity<A> { type Target = A; fn deref(&self) -> &Self::Target { &self.0 } }
内容的提问来源于stack exchange,提问作者AminMal
相关产品推荐
相关产品推荐

