作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
昨天我和几个同事在探索Shapeless,我们决定写一个玩具方法来向case类的第一个参数添加一个,当该参数是Int
时。 :
def addOneToCaseClass[C, H <: HList, E, T <: HList]
(c: C)
(implicit gen: Generic.Aux[C, H],
h: IsHCons.Aux[H, E, T],
ev: E =:= Int,
ev2: (Int :: T) =:= H
): C = {
val hList = gen.to(c)
val elem = hList.head
val tail = hList.tail
val newElem = elem + 1
gen.from(newElem :: tail)
}
ev2
参数是多余的——当然可以推断出
E :: T =:= Int :: T
,但编译器无法做到这一点。
最佳答案
您的直觉是合理的,但不幸的是 Scala 编译器不够聪明,无法派生 ev2
来自 h
和 ev
.问题是h
仅确定 H
分解为 E :: T
,它不成立相反,即 E
和 T
合并等于 H
.
我能想到的最简洁的表述与你的原著相似,但少了一个见证人,
def addOneToCaseClass[C, R <: HList, T <: HList](c: C)
(implicit
gen: Generic.Aux[C, R],
h: IsHCons.Aux[R, Int, T],
ev: (Int :: T) =:= R) = {
val hList = gen.to(c)
val elem = hList.head
val tail = hList.tail
gen.from(elem+1 :: tail)
}
E =:= Int
的证明。通过使用
h
表明
R
分解为
Int :: T
.但是我们仍然需要证明
Int :: T
等于
R
搬回
gen
与更新的元素。
关于scala - 使用 Shapeless 的方法所需的证据多于必要的证据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27980158/
我是一名优秀的程序员,十分优秀!