我正在为检查实体经济单位模型,使用类型,例如一个小型图书馆检查的类型约束而不是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