在Scala中是否可以创建类似别名的东西,可用于强制执行某些条件?是的,我知道,这听起来有点奇怪,但让我说明一下我的意思。
我们想说我们只想拥有java.lang.Integer
类型的正整数。这个类当然也允许负整数,因此在只允许正整数的情况下使用这种类型就不够了。我模糊的想法是拥有类似强制类型别名"。
// vague idea
object PositiveInteger {
import java.lang.{Integer, Math}
type PositiveInteger = Integer // something like this, but enforced
def apply(value: Int) = new PositiveInteger(Math.abs(value))
}
然后我希望能够定义PositiveInteger
类型的参数和值,并依赖于它们是正面的事实:
def calculate(value: PositiveInteger) = ...
我想避免将类包装在另一个(value)类中,因为我需要重复所有方法或者总是从外部访问包含包装对象的字段。
据我所知,在Scala中这是不可能的,但也许你知道实现这一目标的方法。你呢?
答案 0 :(得分:4)
您可以在scalaz中使用此技术,在类型上添加标记 (http://eed3si9n.com/learning-scalaz/Tagged+type.html)
// Entering paste mode (ctrl-D to finish)
type Tagged[U] = {type Tag = U }
type @@[T, U] = T with Tagged[U]
object Tag {
@inline def apply[T, U](t : T) : T @@ U = t.asInstanceOf[T @@ U]
}
sealed trait PositiveInt
object PositiveInt {
def apply(i : Int) : Int @@ PositiveInt = Tag(Math.abs(i))
def unapply(p : Int @@ PositiveInt) : Option[Int] = Some(p)
}
// Exiting paste mode, now interpreting.
结果是:
defined type alias Tagged
defined type alias $at$at
defined object Tag
defined trait PositiveInt
defined object PositiveInt
scala> PositiveInt(4)
res0: @@[Int,PositiveInt] = 4
scala> PositiveInt(-4)
res1: @@[Int,PositiveInt] = 4
scala> res0 + res1
res2: Int = 8
但这种解决方案并不完美。
scala> PositiveInt(5) - PositiveInt(6)
res4: Int = -1
scala> PositiveInt(PositiveInt(5) - PositiveInt(6))
res5: @@[Int,PositiveInt] = 1
要获得完整的解决方案,您可能必须获得具有完整方法定义的真正类