Scala Nat和x27之和的编译时检查;s
我试图编写一个类型类,Scala Nat和x27之和的编译时检查;s,scala,shapeless,Scala,Shapeless,我试图编写一个类型类,SumEq5,这样它的HListtype参数的前两个字段加起来就是5: trait SumEq5[A] object SumEq5 { def apply[L <: HList](implicit ev: SumEq5[L]): SumEq5[L] = ev implicit def sumEq5Ev[L <: HList, A <: Nat, B <: Nat]( implicit hcons: IsHCons.Aux[L, A,
SumEq5
,这样它的HList
type参数的前两个字段加起来就是5
:
trait SumEq5[A]
object SumEq5 {
def apply[L <: HList](implicit ev: SumEq5[L]): SumEq5[L] = ev
implicit def sumEq5Ev[L <: HList, A <: Nat, B <: Nat](
implicit hcons: IsHCons.Aux[L, A, B :: HNil],
ev: Sum.Aux[A, B, _5]
): SumEq5[L] = new SumEq5[L] {}
}
trait SumEq5[A]
对象SumEq5{
def apply[L我只有一个部分答案供您参考,即(变通)解决方案,但不了解为什么原始解决方案不能按预期工作
似乎你不能直接要求一个IsHCons.Aux[L,a,B::HNil]
,你需要零碎地做:
IsHCons.Aux[L,A,L2]
,然后
IsHCons.Aux[L2,B,HNil]
因此,本文件汇编:
import shapeless._, nat._, ops.hlist._, ops.nat._
trait SumEq5[A]
object SumEq5 {
def apply[L <: HList](implicit ev: SumEq5[L]): SumEq5[L] = ev
implicit def sumEq5Ev[L <: HList, L2 <: HList, A <: Nat, B <: Nat](
implicit hcons0: IsHCons.Aux[L, A, L2],
hcons: IsHCons.Aux[L2, B, HNil],
ev: Sum.Aux[A, B, _5]
): SumEq5[L] = new SumEq5[L] {}
}
object T {
def main(args: Array[String]): Unit = {
SumEq5[_0 :: _5 :: HNil]
}
}
import shapeless.\uu,nat.\uu,ops.hlist.\uu,ops.nat_
性状表5[A]
对象SumEq5{
def apply[LDale Wijnand和Marcus Henry指出了正确的方向,如果你想推广到任意长度的HList
s,但是如果你真的只想容纳两个元素HList
s,那么下面是一个相当简单的解决方案
scala> import shapeless._, nat._, ops.nat._
import shapeless._
import nat._
import ops.nat._
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait SumEq5[A]
object SumEq5 {
def apply[L <: HList](implicit ev: SumEq5[L]): SumEq5[L] = ev
implicit def sumEq5AB[A <: Nat, B <: Nat]
(implicit ev: Sum.Aux[A, B, _5]): SumEq5[A :: B :: HNil] =
new SumEq5[A :: B :: HNil] {}
}
// Exiting paste mode, now interpreting.
defined trait SumEq5
defined object SumEq5
scala> SumEq5[_0 :: _5 :: HNil]
res0: SumEq5[_0 :: _5 :: HNil]] = SumEq5$$anon$1@658c5e59
trait是空的,那么为什么不干脆newsumeq5[L]
?这很好,但它对我的输入不起作用,不是吗?当人们第一次学习使用递归或归纳类型时,我经常看到这种情况。编译器需要分步进行。Kevin正在尝试获取a::B::HNil的实例,而不首先拥有B::HNil的实例,而不首先拥有HNil的实例。这里的解决方案是回避需要通过添加一个IsHCons层来进行归纳过程。要进行归纳,你需要证明B::HNil小于或等于5,然后A::B::HNil等于5,在两个隐式def中。谢谢,Dale和Marcus!这个回答和评论肯定帮助我了解了更多。事实上,要简单得多。不过,我会假设这个想法就是句柄Any H包含2个或更多元素的列表,前两个元素的总和为5。更新后也可以捕获该案例。哦,是的,杜克。凯文,这是你的答案。
import shapeless._, nat._, ops.hlist._, ops.nat._
trait SumEq5[A]
object SumEq5 {
def apply[L <: HList](implicit ev: SumEq5[L]): SumEq5[L] = ev
implicit def sumEq5Ev[L1 <: HList, L2 <: HList, L3 <: HList, A <: Nat, B <: Nat](
implicit hcons1: IsHCons.Aux[L1, A, L2],
hcons2: IsHCons.Aux[L2, B, L3],
ev: Sum.Aux[A, B, _5]
): SumEq5[L1] = new SumEq5[L1] {}
}
object T {
def main(args: Array[String]): Unit = {
SumEq5[_0 :: _5 :: HNil]
}
}
scala> import shapeless._, nat._, ops.nat._
import shapeless._
import nat._
import ops.nat._
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait SumEq5[A]
object SumEq5 {
def apply[L <: HList](implicit ev: SumEq5[L]): SumEq5[L] = ev
implicit def sumEq5AB[A <: Nat, B <: Nat]
(implicit ev: Sum.Aux[A, B, _5]): SumEq5[A :: B :: HNil] =
new SumEq5[A :: B :: HNil] {}
}
// Exiting paste mode, now interpreting.
defined trait SumEq5
defined object SumEq5
scala> SumEq5[_0 :: _5 :: HNil]
res0: SumEq5[_0 :: _5 :: HNil]] = SumEq5$$anon$1@658c5e59
scala> import shapeless._, nat._, ops.nat._
import shapeless._
import nat._
import ops.nat._
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait SumEq5[A]
object SumEq5 {
def apply[L <: HList](implicit ev: SumEq5[L]): SumEq5[L] = ev
implicit def sumEq5AB[A <: Nat, B <: Nat, T <: HList]
(implicit ev: Sum.Aux[A, B, _5]): SumEq5[A :: B :: T] =
new SumEq5[A :: B :: T] {}
}
// Exiting paste mode, now interpreting.
defined trait SumEq5
defined object SumEq5
scala> SumEq5[_0 :: _5 :: HNil]
res0: SumEq5[_0 :: _5 :: HNil]] = SumEq5$$anon$1@658c5e59