假设
__1
和
__2
是两个延伸的物体
VersionNumber
,有两种不同的类型
_1, _2
那延伸
Nat
在他们里面。编译器拒绝编译有什么原因吗
val foo: VersionInfo = VersionInfo( if (math.random < 0.5) __1 else __2, __2)
?在您当前的代码中,编译器没有理由拒绝它。这意味着你的
VersionInfo
打破外部常量之间的常量路径
γ1
,
γ2
以及内在价值观
major
和
minor
,存储在您的
版本信息
. 例如,一旦你通过
γ1
作为
专业
到
版本信息
foo
,信息
__1.Nat
与相同类型
foo.major.Nat
永远失去。
这很容易解决,只需不丢弃此类型信息,而是将其作为类型参数附加到
版本信息
.
假设您的自然数看起来有点像这样:
sealed trait NaturalNumber
class _3 extends NaturalNumber
class _2 extends _3
class _1 extends _2
class _0 extends _1
class VersionNumber {
type Nat <: NaturalNumber
}
val __0 = new VersionNumber { type Nat = _0 }
val __1 = new VersionNumber { type Nat = _1 }
val __2 = new VersionNumber { type Nat = _2 }
val __3 = new VersionNumber { type Nat = _3 }
type IsEqual[A, B] = A =:= B
type IsLessOrEqual[A, B] = A <:< B
你可以定义
版本信息
和
ResourceManifest
如下:
case class VersionInfo[Major, Minor](
major: VersionNumber { type Nat = Major },
minor: VersionNumber { type Nat = Minor }
)
trait ResourceManifest {
def getResource: Int
type Major <: NaturalNumber
type Minor <: NaturalNumber
}
然后使用它们作为参数类型
getResource
:
def getResource[A, B]
(manifest: ResourceManifest)
(versionInfo: VersionInfo[A, B])
(implicit
maj_check: manifest.Major IsEqual A,
min_check: manifest.Minor IsLessOrEqual B
)
: Unit = println("it compiles, ship it")
一个小小的考验:
val manifest21 = new ResourceManifest {
def getResource = 21
type Major = _2
type Minor = _1
}
val manifest22 = new ResourceManifest {
def getResource = 22
type Major = _2
type Minor = _2
}
getResource(manifest21)(VersionInfo(__2, __1))
getResource(manifest21)(VersionInfo(__2, __2))
// getResource(manifest22)(VersionInfo(__2, __1)) // won't compile, good
getResource(manifest22)(VersionInfo(__2, __2))
在上面的代码中,我尝试使用相同的名称
as in this answer of yours from few months ago
.