【问题标题】:Shapeless HList appender无形 HList 附加器
【发布时间】:2017-09-30 18:37:20
【问题描述】:

我正在尝试编写一个附加HList 的函数,我发现Updater 最接近我想要的:

  def appender[L <: HList, V, Out <: HList](hl: L, k: Witness, v: V)(implicit updater: Updater.Aux[L, FieldType[k.T, V], Out]) : Out = {
    updater(hl, field[k.T](v))
  }

我有这个更新和追加 HList 的函数,但我想禁用更新,只允许追加函数,这样:

val hl = 'field1 ->> 1 :: HNil
appender(hl, 'field2, 2) //should compile
appender(hl, 'field1, 2) //should fail

目前两者都可以编译。无论如何,我可以用 Shapeless 来表达这个约束吗?我想也许可以提出证据证明Out 类型比 in 类型长一个元素?

【问题讨论】:

    标签: scala shapeless


    【解决方案1】:

    使用shapeless.ops.record.LacksKey:

      def appender[L <: HList, V, Out <: HList](hl: L, k: Witness, v: V)(implicit
                                                                         updater: Updater.Aux[L, FieldType[k.T, V], Out],
                                                                         lk: LacksKey[L, k.T]) : Out = {
        updater(hl, field[k.T](v))
      }
    

    【讨论】:

    • @jamborta L LacksKey K 检查列表L 不包含任何带有键K 的元素(检查以确保L 中没有FieldType[K, _] 类型的元素)。这限制了Updater 只能追加到列表中,因为它只能在键已经存在的情况下修改列表
    【解决方案2】:

    对于后代,这是一个使用您的长度检查想法的答案。不过,LacksKey 方式更好。此外,Updater 会在您重复使用某个键但使用不同类型时创建重复键(因为毕竟类型确实是键的一部分),这意味着这个append 也是如此。

    def append[
      Value,
      In  <: HList,
      Out <: HList,
      InSize   <: Nat,
      OutSize  <: Nat,
      AddedNum <: Nat
    ](in: In, key: Witness, value: Value)(implicit
      update: Updater.Aux[In, FieldType[key.T, Value], Out],
      inSize:  Length.Aux[In,  InSize],
      outSize: Length.Aux[Out, OutSize],
      addedNum: ops.nat.Diff.Aux[OutSize, InSize, AddedNum], // ops.{hlist, nat}.Diff conflict
      sizeRestriction: AddedNum =:= _1 // Bonus: error messages are fairly readable: "Cannot prove that AddedNum = Succ[_0]" (followed by a horrifyingly long "not enough arguments" error).
    ): Out = update(in, field[key.T](value))
    

    请注意,计算中的所有类型级值都必须是类型参数,因为您不能在同一参数列表中拥有提及其他参数的类型的参数。您需要非常小心,不要要求编译器做的事情超出它可以处理的每一步。

    【讨论】:

    • 谢谢。这是一种有趣的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-18
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    相关资源
    最近更新 更多