scala – HList#foldLeft()返回什么?
我正在尝试使用来自Shapeless的HList.
这是我的第一次尝试: trait Column[T] { val name: String } case class CV[T](col: Column[T],value: T) object CV { object columnCombinator extends Poly2 { implicit def algo[A] = at[(String,String,String),CV[A]] { case ((suffix,separator,sql),cv) ? (suffix,if (sql == "") cv.col.name+suffix else sql+separator+cv.col.name+suffix) } } def combine[A <: HList](columns: A,suffix: String,separator: String = " and ") (implicit l: LeftFolder[A,(String,columnCombinator.type]): String = columns.foldLeft((suffix,""))(columnCombinator)._3 } 问题是我不知道foldLeft在这个例子中返回了什么. 我希望它返回(String,但编译器告诉我返回l.Out.什么是l.Out? 猜测源代码有点复杂. 网上没有太多关于此的信息. 我咨询过的一些信息: > Shapeless Tests 解决方法
您的combine方法返回所谓的
“dependent method type”,这意味着它的返回类型取决于它的一个参数 – 在这种情况下是一个路径依赖类型,在其路径中包含l.
在许多情况下,编译器将静态地知道有关依赖返回类型的内容,但在您的示例中却没有.我将尝试在一秒钟内解释原因,但首先考虑以下更简单的例子: scala> trait Foo { type A; def a: A } defined trait Foo scala> def fooA(foo: Foo): foo.A = foo.a fooA: (foo: Foo)foo.A scala> fooA(new Foo { type A = String; def a = "I'm a StringFoo" }) res0: String = I'm a StringFoo 这里res0的推断类型是String,因为编译器静态地知道foo参数的A是String.但是,我们不能写下列任何一种: scala> def fooA(foo: Foo): String = foo.a <console>:12: error: type mismatch; found : foo.A required: String def fooA(foo: Foo): String = foo.a ^ scala> def fooA(foo: Foo) = foo.a.substring <console>:12: error: value substring is not a member of foo.A def fooA(foo: Foo) = foo.a.substring ^ 因为这里编译器不静态地知道foo.A是String. 这是一个更复杂的例子: sealed trait Baz { type A type B def b: B } object Baz { def makeBaz[T](t: T): Baz { type A = T; type B = T } = new Baz { type A = T type B = T def b = t } } 现在我们知道不可能为A和B创建一个具有不同类型的Baz,但是编译器没有,所以它不会接受以下内容: scala> def bazB(baz: Baz { type A = String }): String = baz.b <console>:13: error: type mismatch; found : baz.B required: String def bazB(baz: Baz { type A = String }): String = baz.b ^ 这正是你所看到的.如果我们查看shapeless.ops.hlist中的代码,我们可以说服自己,我们在这里创建的LeftFolder将具有相同的In和Out类型,但编译器不能(或者更确切地说不是 – 它是一个设计决定)在这个推理中跟随我们,这意味着它不会让我们对待l.Out作为没有更多证据的元组. 幸运的是,由于LeftFolder.Aux,它只是LeftFolder的别名,Out类型成员作为第四个类型参数,因此很容易提供证据: def combine[A <: HList](columns: A,separator: String = " and ")( implicit l: LeftFolder.Aux[ A,columnCombinator.type,String) ] ): String = columns.foldLeft((suffix,""))(columnCombinator)._3 (您也可以在l类型中使用类型成员语法和普通的旧LeftFolder,但这会使这个签名更加混乱.) columns.foldLeft(…)(…)部分仍然返回l.Out,但现在编译器静态地知道这是一个字符串元组. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Angular Universal TransferState未在客户端上加载
- 为什么Scala说它看不到org.joda.time.Period的成员?
- 如何使用oauth保护restful webservice?
- UNIX编程专题-可重入函数和不可重入函数
- vim – 如何为CoffeeScript生成ctags?
- 如何/何时执行Shell标记一个构建失败在Jenkins?
- webservice-client – 使用JDK8的WebService客户端生成错误
- Shell执行命令并把结果写入文件
- -bash: ls: No such file or directory 产生的原因及修改方
- scala – 部分应用类型参数