我正在爲檢查實體經濟單位模型,使用類型,例如一個小型圖書館檢查的類型約束而不是val apples = 2.0
我們寫val apples = GoodsAmount[KG, Apples](2.0)
。爲了創建一攬子商品,我試圖使用無形庫中的HList。這工作正常,但在某些情況下,我不能像我更喜歡的通用代碼。見例如下面的問題。無形:多態函數
我先從一個簡單的代碼來解釋我想提升到無形的東西。我們創建兩個類,代表Km,另一個Miles。應該允許添加公里等級,但不允許里程。我使用抽象類型T的主要動機是我們更復雜的庫。對'+'函數的間接調用僅僅是因爲我們在後面的不成形情況下需要類似的東西。
trait Foo {
type T
val v: Double
def +[B <: Foo](other: B)(implicit ev: this.T =:= other.T) = v + other.v
}
trait _Km
trait _Miles
case class Km(v: Double) extends Foo { type T = _Km }
case class Miles(v: Double) extends Foo { type T = _Miles }
object ExampleSimple extends App {
def add[A <: Foo, B <: Foo](a: A, b: B)(implicit ev: a.T =:= b.T) = { a + b }
add(Km(1), Km(2))
// add(Km(1), Miles(2)) /* does not compile as intended */
}
這按預期工作。但有必要對'添加'功能進行類型限制檢查。我試圖將其擴展到HLists看起來是這樣的:
object ExampleShapeless extends App {
import shapeless._
val l1 = Km(1) :: Km(2) :: HNil
val l2 = Km(4) :: Km(3) :: HNil
object add extends Poly1 {
implicit def caseTuple[A <: Foo] = at[(A,A)] { case (a, b) => a + b }
}
(l1 zip l2).map(add)
}
但是,這產生了以下錯誤消息(使用Scala的2.10.2):
[error] /home/fuerst/gitg3m/code/types/src/main/scala/lagom_d/extract.scala:50: Cannot prove that a.T =:= b.T.
[error] implicit def caseTuple[A <: Foo] = at[(A,A)] { case (a: Foo, b) => a + b }
[error] ^
[error] /home/fuerst/gitg3m/code/types/src/main/scala/lagom_d/extract.scala:54: could not find implicit value for parameter mapper: shapeless.Mapper[ExampleShapeless.add.type,shapeless.::[(Km, Km),shapeless.::[(Km, Km),shapeless.HNil]]]
[error] (l1 zip l2).map(add)
的第一個錯誤應該是固定的,在案件我可以添加一個類型約束到caseTuple函數,但說實話,我還沒有理解at函數是如何工作的以及我可以在哪裏添加隱式證據參數。而且我也不知道,我必須做什麼,以便Mapper能找到他的隱含價值。
一個不太通用版本,在那裏我有
implicit def caseTuple = at[(Km,Km)] { case (a, b) => a + b }
replase的caseTuple功能工作正常,但對我們目前的解決方案使用需要編寫大量的冗餘代碼(好吧,這個解決方案將是猶未元組)。有人能給我一個提示,我怎麼能解決這個問題?
感謝, Klinke
你可以試着來定義你的'Foo'這樣的:'特質富[T <:美孚] {V:雙; +(t T):T = ...}'。 Km級(val v:Double)擴展Foo [Km]'。 'implicit def add [T] = at [(Foo [T],Foo [T])]' – senia