我有兴趣测试两个HList异构记录是否相同&#34 ;;也就是说,它们具有相同的键/值对,但不一定是相同的顺序。是否有预定义的类型谓词执行EquivHLists
在下面的代码片段中执行的操作?
// shapeless heterogeneous records with "equivalent" types.
// these should compile if given as the arguments to 'f' below.
val hrec1 = ("a" ->> 1) :: ("b" ->> 2) :: HNil
val hrec2 = ("b" ->> 2) :: ("a" ->> 1) :: HNil
// only compiles if two HList records contain same information
def f(hr1: H1 <: HList, hr2 : H2 <: HList)(implicit equiv: EquivHLists[H1, H2]) = {
// biz logic
}
答案 0 :(得分:4)
我相信Align[M,L]
类型类支持您想要的内容,它允许您重新排列一个hlist的元素以匹配具有相同类型的另一个hlist的顺序。
这是我认为你想要的功能。它将告诉您两个等效的hlists是否对每种类型具有相同的值。如果两个列表没有相同的类型,则不会编译。
import shapeless._
import ops.hlist._
def equiv[H <: HList, L <: HList]
(h : H, l : L)(implicit align: Align[H, L]): Boolean = align(h) == l
scala> equiv(3 :: "hello" :: HNil, "hello" :: 3 :: HNil)
res11: Boolean = true
scala> equiv(4 :: "hello" :: HNil, "hello" :: 3 :: HNil)
res12: Boolean = false
scala> equiv(4 :: "hello" :: HNil, "hello" :: 3.0 :: HNil)
<console>:19: error: could not find implicit value for parameter align: shapeless.ops.hlist.Align[Int :: String :: shapeless.HNil,String :: Double :: shapeless.HNil]
编辑:经过一些进一步的实验,如果hlists有多个相同类型的值,这将给出漏报:
scala> equiv(3 :: "hello" :: 4 :: HNil, 4 :: "hello" :: 3 :: HNil)
res14: Boolean = false
这是因为Align
的工作方式:它基本上只迭代一个hlist,并以相同的类型拉出另一个的第一个元素。但是,如果您使用单身类型的文字,那么这不应该是一个问题。
所以这个 使用上述记录至少与键有关:
scala> equiv(hrec1, hrec2)
res16: Boolean = true
//change one of the keys
scala> val hrec3 = ("c" ->> 2) :: ("a" ->> 1) :: HNil
hrec3: Int with shapeless.labelled.KeyTag[String("c"),Int] :: Int with shapeless.labelled.KeyTag[String("a"),Int] :: shapeless.HNil = 2 :: 1 :: HNil
scala> equiv(hrec1, hrec3)
<console>:27: error: could not find implicit value for parameter align ...
//change one of the values, it compiles but returns false
scala> val hrec4 = ("b" ->> 2) :: ("a" ->> 3) :: HNil
hrec4: Int with shapeless.labelled.KeyTag[String("b"),Int] :: Int with shapeless.labelled.KeyTag[String("a"),Int] :: shapeless.HNil = 2 :: 3 :: HNil
scala> equiv(hrec1, hrec4)
res18: Boolean = false
答案 1 :(得分:0)
def f(hr1: H1 <: HList, hr2 : H2 <: HList)(implicit equiv: H1 =:= H2) = {
// biz logic
}
我相信这应该做你想要的,你试过吗?