【问题标题】:How do I append an element to a KList?如何将元素附加到 KList?
【发布时间】:2020-04-17 17:26:51
【问题描述】:

如何在保持 KList 的原始类型的同时将元素附加到 KList?我对 shapeless 还很陌生,我真的不清楚函数可以期待什么类型。

下面是我正在尝试做的一个例子。我想使用类型约束来确保所有值都符合Box[_],但我也尝试了一个使用普通HList 的不受约束的示例,但仍然无法编译。

import shapeless._
import shapeless.UnaryTCConstraint.*->*

case class Box[T](value: T)

case class BoxBuilder[B <: HList](boxes: B) {
  def add[T](box: Box[T]): BoxBuilder[HList] = {
    this.copy(boxes = boxes :+ box)
  }
}

case class BoxBuilderTC[B <: HList : *->*[Box]#λ](boxes: B) {
  def add[T](box: Box[T]): BoxBuilder[HList] = {
    this.copy(boxes = boxes :+ box)
  }
}

我可能在这里遗漏了一些关于 shapeless 的基础知识,因此欢迎提供任何其他提示/建议。

【问题讨论】:

    标签: scala generics types functional-programming shapeless


    【解决方案1】:

    尝试添加必要的隐式参数/上下文边界

    import shapeless._
    import shapeless.UnaryTCConstraint.*->*
    import shapeless.ops.hlist.Prepend
    
    case class Box[T](value: T)
    
    case class BoxBuilder[B <: HList](boxes: B) {
      def add[T](box: Box[T])(implicit prepend: Prepend[B, Box[T] :: HNil]): BoxBuilder[prepend.Out] = {
        this.copy(boxes = boxes :+ box)
      }
    }
    
    case class BoxBuilderTC[B <: HList : *->*[Box]#λ](boxes: B) {
      def add[T, Out <: HList : *->*[Box]#λ](box: Box[T])(implicit
                                            prepend: Prepend.Aux[B, Box[T] :: HNil, Out]
      ): BoxBuilderTC[Out] = {
        this.copy(boxes = boxes :+ box)
      }
    }
    

    通常只写HList 而不是HList 的特定子类型太粗糙了。

    【讨论】:

    • 啊,太好了——这正是我想要的。我会在这里为未来的读者 FWIW 留个便条。即使编译器没有,IntelliJ 似乎也会在此处报告无约束示例的“类型不匹配”错误。它说:Type Mismatch. Required: prepend.Out. Found: Prepend[B, Box[T] :: HNil]#Out。我不清楚为什么它不认为这两者是等价的。对于受约束的示例,它不会报告类似的错误。
    • @AlanThomas 他们不等价。前者是后者的一个亚型。 (这与 IntelliJ 相关,与 Scala 无关)。
    • @AlanThomas,我在 2019.2 版本中遇到了同样的问题,在 2020.1 版本中没有发生。但是对于受限示例,它给出了一个错误。
    猜你喜欢
    • 1970-01-01
    • 2023-01-16
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    相关资源
    最近更新 更多