gpt4 book ai didi

scala - Shapeless:检查多态函数的类型约束

转载 作者:行者123 更新时间:2023-12-04 11:54:13 25 4
gpt4 key购买 nike

我正在开发一个用于经济模型的小型库,用于检查实体的单位,使用类型,例如而不是 val apples = 2.0我们写 val apples = GoodsAmount[KG, Apples](2.0) .为了创建商品包,我尝试使用 shapeless 库中的 HLists。这工作正常,但在某些情况下,我不能像我喜欢的那样通用代码。见例如下面的问题。

我从一个简单的代码开始,它解释了我想要提升为无形的东西。我们创建了两个类,分别代表 Km 和其他 Miles。应该允许添加公里级别,但不能添加英里。我使用抽象类型 T 的主要动机是我们更复杂的库。而对'+'函数的间接调用只是因为我们需要在后面的shapeless case中类似的东西。

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 找到他的隐含值(value)。

一个不太通用的版本,我用

implicit def caseTuple = at[(Km,Km)] { case (a, b) => a + b }

工作正常,但需要编写大量冗余代码(好吧,这个解决方案仍然比我们当前使用元组的解决方案更好)。有人可以给我一个提示,我该如何解决这个问题?

谢谢,
克林克

最佳答案

您可以通过向案例添加类型参数来要求类型成员匹配:

object add extends Poly1 {
implicit def caseTuple[_T, A <: Foo { type T = _T }] = at[(A, A)] {
case (a, b) => a + b
}
}

或者您可以使用存在类型,因为您只关心它们是否相同:
object add extends Poly1 {
implicit def caseTuple[A <: Foo { type T = _T } forSome { type _T }] =
at[(A, A)] {
case (a, b) => a + b
}
}

任一版本都将提供您想要的行为。

关于scala - Shapeless:检查多态函数的类型约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17346143/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com