2015-02-06 26 views
0

我試圖擴展使用值類爲類型安全的想法,這裏描述的http://docs.scala-lang.org/overviews/core/value-classes.html到一個更抽象的版本,允許隱式轉換。例如,我有一些措施特質Scala:隱式值查找與類型類成語

trait Measure { 
implicit def +[B <: Measure](other: B): Measure 
val value: Double 
} 

和一些實現

//this will compile because [_ , Meters] is not ambiguous since 
//for this example im only using one conversion. see below 


case class Meters(value: Double) extends Measure { 
    def +[B <: Measure](other: B): Meters = Meters(other.value * implicitly[Converter[_ , Meters]].factor + this.value) } 
case class Fathoms(value: Double) extends Measure { 
    def +[B <: Measure](other: B): Fathoms = Fathoms(other.value * implicitly[Converter[_ , Fathoms]].factor + this.value) } 

和轉換特徵和實施隱式查找機制找到

trait Converter[F, T]{ 
    val factor: Double 
} 
implicit object Meter2Fathom extends Converter[Meter, Fathom]{ 
    val factor: Double = .556 
} 
implicit object Fathom2Meter extends Converter[Fathom, Meter]{ 
    val factor: Double = 1.8 
} 

有沒有一種辦法在「無論B是什麼」上定義Converter實現?如果我們嘗試將兩個不存在轉換因子的度量值相加,但仍然能夠進行編譯,則需要運行時錯誤。

//will not compile of course. the idea is to somehow reify whatever B 
// is and look that implicit converter up, instead of actual B. 
case class Meters(value: Double) extends Measure { 
    def +[B <: Measure](other: B): Meters = Meters(this.value + other.value * implicitly[Converter[* B *, Meters]].factor 
+2

這些類型的問題的一般設計解決方案是假設'Measure'的一個表示是標準的..可以說'Meter'。而所有......其他度量將執行'toStandard'或'toMeter'和'fromStandard'或'fromMeter'函數。現在,在'Meter'中完成所有計算......然後使用'fromMeter'將其轉換爲'Mesure'。 – 2015-02-06 13:54:32

+0

其他功能更純粹但更高級的方法可以使用'adhoc-polymorphism'與Type-classes ...非常好的讀取類型類 - > http://danielwestheide.com/blog/2013/02/06/新手指南到scala部分-12型-class.html – 2015-02-06 13:57:15

+0

這可能是一條路要走的路。轉換中的另一個計算步驟減輕了對n^2轉換因子的需求。 +1 – Azeli 2015-02-07 01:21:16

回答