Shapeless:尝试通过其类型限制HList元素

7

问题1 - 基本的LUBConstraints

我尝试使用现有的LUBConstraints进行操作时遇到了缺少证据的失败情况(请参阅以下代码块)。是否可以给出任何提示?空列表不是一个有效的长整型列表吗?没有元素违反了约束条件。

import shapeless.ops.coproduct
import shapeless.{::, :+:, Coproduct, HNil, HList}

object testLUBConstraints {
  import shapeless.LUBConstraint._

  // !!! see comment on question - this satisfies the implicit below!!! 
  // implicit val hnilLUBForLong = new LUBConstraint[HNil.type, Long] {}

  def acceptLong[L <: HList : <<:[Long]#λ](l: L) = true
  val validLong = acceptLong(1l :: HNil)

  val validEmpty = acceptLong(HNil)
  //  => WHY??? Error: could not find implicit value for evidence parameter of type shapeless.LUBConstraint[shapeless.HNil.type,Long]
  //  MY EXPECTATION WAS: 'implicit def hnilLUB[T] = new LUBConstraint[HNil, T] {}' defined within LUBConstraint companion should provide so

  // val invalid = acceptLong(1.0d :: HNil) -> fails due to missing evidence (as expected)
}

非常感谢您的支持。

问题2 - 使用Coproduct拥有自己的约束条件 (分为一个单独的问题:Shapeless:使用Coproduct拥有自己的HList约束条件

问题3 - 通过参数类型限制case classes (分为一个单独的问题:Shapeless:限制case class类型


我通过在代码块_Question 1_中局部声明implicit val hnilLUBForLong = new LUBConstraint[HNil.type, Long] {}来解决第一个错误。似乎声明的方法提供的隐式值并不完全匹配类型:LUBConstraint[HNil, Long] =!= LUBConstraint[HNil.type, Long]。这是意图还是一个错误? - sthielo
正在处理CPConstraint的隐式解析(请参见_Question 2_)。假设有val hlLong: ::[Long, HNil] = 1L :: HNil,并且通过implicit val cpcLong = implicitly[CPConstraint[hlLong.type, CPType]]隐式查找CPConstraint。我尝试了implicit val scpcEmptyLong1: CPConstraint[::[Long,HNil], CPType] = new CPConstraint[::[Long,HNil], CPType] {},但它不符合隐式搜索,而implicit val scpcEmptyLong2: CPConstraint[hlLong.type, CPType] = new CPConstraint[hlLong.type, CPType] {}则符合。-为什么?有什么区别? - sthielo
这可能应该是三个单独的问题。在第一种情况下,您可以通过将HNil显式地类型化为HNil来解决问题:acceptLong(HNil: HNil)应该编译。 - Travis Brown
好的 - 我会尝试将问题分开。 - sthielo
@TravisBrown - 谢谢,显式类型有所帮助。 - sthielo
@TravisBrown 不过,稍微更加开放的声明是否可以避免显式类型:例如 implicit def hnilLUB[HN <: HNil, T] = new LUBConstraint[HN, T] {} - 这是否值得提出改进建议? - sthielo
1个回答

6
< p>值HNil的推断类型将是单例类型HNil.type,它是HNil的适当子类型。因为像LUBConstraint这样的类型类是不变的,如果你要求HNil.type的实例,则不会找到任何可用的HNil实例。

已经有一些讨论改变HNil的定义,使其可以工作,但这并不是微不足道的,而且不清楚更改的所有影响是否都是理想的。在此期间,您可以编写HNil:HNil来升级该值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接