2015-06-23 31 views
4

Scala中可能創建類似別名的東西可用於強制某些條件嗎?是的,我知道,這聽起來有點奇怪,但讓我說明我的意思。在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) = ... 

我想避免在另一個包裝類(值)類,因爲我需要重複所有的方法或總是從外部訪問一個包含包裝對象的字段。

據我所知,這在斯卡拉是不可能的,但也許你知道一種方法來實現這一點。你做?

回答

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 

要獲得完整的解決方案,您可能需要得到全法定義一個真正的類