如何让 scala 编译器从一种类型推断另一种类型?

问题描述 投票:0回答:1

我想创建一个 Scala Id 类型类,例如,我可以声明 Foo 类型的 Id 采用 Long 值,例如

val fooId: Id[Foo] = Id(12L) // type-safe at compile time
val fooIdValue: Long = fooId.value // able to get the value back out

我尝试了各种方法,但似乎无法强制执行这些限制。如果我声明

trait WithId[I] {
  type Id = I
}

case class Id[A <: WithId[_]](value: A#Id) // A#Id => Any, not what I want!

class Foo extends WithId[Long] {
  type Id = Long
}

这允许

val fooId: Id[Foo] = Id("foo") // should be illegal unless a Long

如果我将 WithId 更改为使用抽象类型

trait WithId {
  type Id
}

case class Id[A <: WithId](value: A#Id)

class Foo extends WithId {
  type Id = Long
}

然后

val fooId: Id[Foo] = Id(12L)

无法编译,说

no type parameters for method apply: (value: A#Id)net.box.Id[A] in object Id exist so that it can be applied to arguments (Long)  --- because --- argument expression's type is not compatible with formal parameter type;  found   : Long  required: ?0A#Id

我怎样才能说并强制执行 Id[Foo] 需要 Long?

scala types typeclass parameterized
1个回答
3
投票

您在

WithId
上删除该类型参数是正确的。 然而,出现的第二个问题是由您实例化
Id
的方式引起的。 当您说
val x: Foo[T]
时,您指定了您想要
x
具有的类型,但您并没有真正帮助编译器确定
Foo
在构造时应使用什么类型。 所以...编译器错误,您通过对
Foo
说您想要
Id
中的
A
得到结果,但您还没有告诉
Foo
A
是什么! 要修复它,只需将您的用法更改为

val fooId = Id[Foo](12L)
© www.soinside.com 2019 - 2024. All rights reserved.