gpt4 book ai didi

scala - 如何使用 foldRight/foldLeft 将 HList 转换为另一个 HList

转载 作者:行者123 更新时间:2023-12-03 14:19:25 25 4
gpt4 key购买 nike

这个问题来源于我之前的问题:What does HList#foldLeft() return?

我有这个场景:

class Cursor {
}

trait Column[T] {
def read(c: Cursor, index: Int): T
}

object Columns {
object readColumn extends Poly2 {
implicit def a[A, B <: HList] = at[Column[A], (B, Cursor, Int)] { case (col, (values, cursor, index)) ⇒
(col.read(cursor, index) :: values, cursor, index+1)
}
}

def readColumns[A <: HList, B <: HList](c: Cursor, columns: A)(implicit l: RightFolder.Aux[A, (HNil.type, Cursor, Int), readColumn.type, (B, Cursor, Int)]): B =
columnas.foldRight((HNil, c, 0))(readColumn)._1
}

此代码尝试读取几列的值。

如果我打电话 readColumns(cursor, new Column[String] :: new Column[Int] :: HNil) , 我希望得到 String :: Int :: HNil .
readColumns()方法编译正常,但编译器提示具体调用中的隐式。

什么是正确的工作方式?

更新 1 :

这是我在使用 2 列调用时收到的确切错误消息:
could not find implicit value for parameter l: 
shapeless.ops.hlist.RightFolder.Aux[shapeless.::[Column[String],shapeless.::
[Column[String],shapeless.HNil]],(shapeless.HNil.type, android.database.Cursor, Int),readColumn.type,(B, android.database.Cursor, Int)]

不知道如何帮助编译器。 :-(

更新 2 :

问题:为什么指定 HNil.typereadColumns() 的隐式参数中: RightFolder.Aux[A, (HNil.type, Cursor, Int), readColumn.type, (B, Cursor, Int)] ?

最佳答案

更新地址编辑

这是一个完整的工作示例:

class Cursor {}

trait Column[T] {
def read(c: Cursor, index: Int): T
}

import shapeless._, ops.hlist.RightFolder

object Columns {
object readColumn extends Poly2 {
implicit def a[A, B <: HList]: Case.Aux[
Column[A],
(B, Cursor, Int),
(A :: B, Cursor, Int)
] = at[Column[A], (B, Cursor, Int)] {
case (col, (values, cursor, index)) =>
(col.read(cursor, index) :: values, cursor, index + 1)
}
}

def readColumns[A <: HList, B <: HList](c: Cursor, columns: A)(implicit
l: RightFolder.Aux[
A,
(HNil, Cursor, Int),
readColumn.type,
(B, Cursor, Int)
]
): B = columns.foldRight((HNil: HNil, c, 0))(readColumn)._1
}

进而:
val stringColumn = new Column[String] {
def read(c: Cursor, index: Int) = "foo"
}

val intColumn = new Column[Int] {
def read(c: Cursor, index: Int) = 10
}

Columns.readColumns(new Cursor, stringColumn :: intColumn :: HNil)

这编译得很好,并且在 2.0.0 和 2.1.0-RC1 上都符合我的预期。

我应该在我原来的回答中提到使用 HNil.type这样并不理想——它工作得很好,但明确输入 HNilfoldRight 的参数中如 HNil是更好的解决方案。请注意,您必须执行其中一项,因为 HNil 的静态类型是 HNil.type , 和 RightFolder在它的第二个参数中不是协变的。

原答案

您的 readColumn 中有一个非常小的错误定义——你返回一个 Tuple4 ,但你想返回一个 Tuple3 .以下应该工作:
    object readColumn extends Poly2 {
implicit def a[A, B <: HList]: Case.Aux[
Column[A],
(B, Cursor, Int),
(A :: B, Cursor, Int)
] = at[Column[A], (B, Cursor, Int)] {
case (col, (values, cursor, index)) =>
(col.read(cursor, index) :: values, cursor, index+1)
}
}

由于与隐式解析无关的原因,为任何隐式方法提供显式返回类型通常是一个好主意,但在这种情况下,显式返回类型也会很快出现错误。

关于scala - 如何使用 foldRight/foldLeft 将 HList 转换为另一个 HList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26631231/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com