使用隐式类型证据来满足类型约束
Posted
技术标签:
【中文标题】使用隐式类型证据来满足类型约束【英文标题】:Using implicit type evidence to satisfy type constraint 【发布时间】:2022-01-19 05:45:35 【问题描述】:我正在尝试创建一个具有许多不受约束类型的构建器,该构建器可以构建具有约束类型的类。如何使用类型边界的隐式证据来满足类型约束?
比如说我想建一个类:
class NameClass[N <: String](name: N)
我使用的是这样的构建器:
class NameClassBuilder[N](n: N)
def name[NewN <: String](name: NewN) = new NameClassBuilder[NewN](name)
def build(implicit ev: N <:< String) : NameClass[N] = new NameClass[N](n)
object NameClassBuilder
def builder : NameClassBuilder[Unit] = new NameClassBuilder[Unit]()
这个想法是您可以从一个虚拟类型/值开始,然后在添加字段时更新类型。通过使用类型正确的证据,您只能在类型有意义时构建它。
问题在于它无法编译,因为来自NameClassBuilder
的N
不满足NameClass
中的类型约束N <: String
,即使我已经提供了它的证据。
error: type arguments [N] do not conform to class NameClass's type parameter bounds [N <: String]
def build(implicit ev: N <:< String) : NameClass[N] = new NameClass[N](n)
有没有什么办法可以利用证据来满足这个约束?
【问题讨论】:
【参考方案1】:您可以改为返回NameClass[N with String]
。 N with String <: String
代表任何 N
,如果实际上是 N <: String
,则 N with String = N
。 build
中的 N <:< String
需要将 n: N
转换为 N with String
。
def build(implicit ev: N <:< String): NameClass[N with String] =
type F[+X] = N with X
new NameClass(ev.liftCo[F](n))
Complete example on Scastie
【讨论】:
不错!我发现我可以只使用.asInstanceOf[N with String]
,但这要好得多。【参考方案2】:
您是在告诉编译器,当调用函数build
时,应该存在符合N <:< String
的隐含证据。但在NameClassBuilder
范围内,N
符合Any
。
你可以试试:
class NameClassBuilder[N](n: N)
def name[NewN <: String](name: NewN) = new NameClassBuilder[NewN](name)
def build[U <: String](implicit ev: N <:< String): NameClass[U] = new NameClass[U](n.asInstanceOf)
【讨论】:
以上是关于使用隐式类型证据来满足类型约束的主要内容,如果未能解决你的问题,请参考以下文章