【问题标题】:leftReduce Shapeless HList of generic typesleftReduce 泛型类型的无形 HList
【发布时间】:2014-06-03 12:11:48
【问题描述】:

这基本上就是我想要的:

case class Foo[T](x: T)

object combine extends Poly {
  implicit def caseFoo[A, B] = use((f1: Foo[A], f2: Foo[B]) => Foo((f1.x, f2.x)))
}

def combineHLatest[L <: HList](l: L) = l.reduceLeft(combine)

所以combineHLatest(Foo(1) :: Foo("hello") :: HNil) 应该产生Foo( (1, "hello") )

上面没有编译,因为它找不到隐式 LeftReducer 但我不知道如何实现一个。

【问题讨论】:

标签: scala shapeless


【解决方案1】:

昨晚我回答这个问题时已经很晚了,虽然下面原始答案中的信息是正确的,但这不一定是最有帮助的演示文稿。

您有充分的理由不知道如何实施LeftReducer,因为这不是您的工作。编译器将创建您需要的类型类的任何有效实例——您只需确保它具有需要的所有信息。

例如,以下内容适用于您的实现:

scala> (Foo(1) :: Foo("hello") :: HNil).reduceLeft(combine)
res0: Foo[(Int, String)] = Foo((1,hello))

这里编译器可以看到你想要减少的HList的类型,并且可以创建合适的LeftReducer实例。

另一方面,当您将对leftReduce 的调用封装在一个方法中时,编译器对您调用它的列表一无所知,除非您明确告诉它。在combineHLatest 的实现中,编译器知道LHList,但仅此而已——它没有任何证据表明它可以执行归约。幸运的是,很容易通过隐式参数给它这个证据(见下面的原始答案)。


我最初在这里为扁平元组问题发布了一种笨拙的解决方案,但笨拙只是因为我最初尝试中的一个小错字。实际上可以编写一个相当优雅的实现:

def combineHLatest[L <: HList, R <: HList](l: L)(implicit
  r: RightFolder.Aux[L, Foo[HNil], combine.type, Foo[R]],
  t: Tupler[R]
) = Foo(l.foldRight(Foo(HNil: HNil))(combine).x.tupled)

(我的错误是写R 而不是Foo[R] 作为Aux 的最后一个类型参数。)


原答案

如果您确保您的方法有证据表明它可以对输入执行归约,这将按预期工作:

import shapeless._, ops.hlist.LeftReducer

def combineHLatest[L <: HList](l: L)(implicit r: LeftReducer[L, combine.type]) =
  l.reduceLeft(combine)

但请注意,如果您有两个以上的参数,这种方法只会构建一个嵌套元组,因此您可能想要更像这样的东西:

object combine extends Poly {
  implicit def caseFoo[A, B <: HList] = use(
    (f1: Foo[A], f2: Foo[B]) => Foo(f1.x :: f2.x)
  )
}

def combineHLatest[L <: HList](l: L)(implicit
  r: RightFolder[L, Foo[HNil], combine.type]
) = l.foldRight(Foo(HNil: HNil))(combine)

然后例如:

scala> println(combineHLatest(Foo(1) :: Foo("hello") :: Foo('a) :: HNil))
Foo(1 :: hello :: 'a :: HNil)

如果您想要一个(扁平化)元组,那也很简单。

【讨论】:

  • 谢谢 Travis,看起来很完美。
  • 其实我想要一个元组,还在苦苦寻找如何做,但我会狠狠地盯着它,直到它成功为止。
猜你喜欢
  • 2021-02-18
  • 1970-01-01
  • 2017-02-10
  • 1970-01-01
  • 2020-04-06
  • 1970-01-01
  • 1970-01-01
  • 2015-11-20
  • 1970-01-01
相关资源
最近更新 更多