本文介绍了压缩 HList 的推断函数类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

感谢 https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0 我了解如何压缩 shapeless HList:

Thanks to https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0 I understand how to zip shapeless HLists:

从 Shapeless 2.0.0-M1 导入一些东西:

Import some stuff from Shapeless 2.0.0-M1:

import shapeless._
import shapeless.ops.hlist._
import syntax.std.tuple._
import Zipper._

创建两个 HList:

Create two HLists:

scala> val h1 = 5 :: "a" :: HNil
h1: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 5 :: a :: HNil

scala> val h2 = 6 :: "b" :: HNil
h2: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 6 :: b :: HNil

压缩它们:

scala> (h1, h2).zip
res52: ((Int, Int), (String, String)) = ((5,6),(a,b))

现在尝试定义一个做同样事情的函数:

Now try to define a function that does the same thing:

scala> def f[HL <: HList](h1: HL, h2: HL) = (h1, h2).zip
f: [HL <: shapeless.HList](h1: HL, h2: HL)Unit

推断的返回类型是 Unit,实际上将 f 应用于 h1 和 h2 就是这样做的:

The inferred return type is Unit, and indeed applying f to h1 and h2 does just that:

scala> f(h1, h2)

scala>

在这种情况下,有没有办法定义 f 以便我得到 ((5,6),(a,b)) ?

Is there a way to define f such that I get ((5,6),(a,b)) back in this case?

最终我想要做的是定义一个函数来压缩两个 HList,然后映射它们,基于抛硬币选择 _1 或 _2,这将产生另一个 HL.

Ultimately what I'm trying to do is define a function that zips the two HLists and then maps over them, choosing either _1 or _2 based a coin toss, which would yield another HL.

object mix extends Poly1 {
  implicit def caseTuple[T] = at[(T, T)](t =>
    if (util.Random.nextBoolean) t._2 else t._1)
}

在 REPL 中运行良好:

Which works fine in the REPL:

scala> (h1, h2).zip.map(mix)
res2: (Int, String) = (5,b)

但是当我试图将它拉入一个函数时,我被上述问题绊倒了.

But I'm getting tripped up on the above issue when trying to pull this into a function.

谢谢!

推荐答案

您可以使用 Zip(或在本例中为 Zip.Aux) 类型类:

You can wrap everything up in one method using the Zip (or in this case Zip.Aux) type class:

import shapeless._, shapeless.ops.hlist._

object mix extends Poly1 {
  implicit def caseTuple[T] = at[(T, T)](t =>
    if (util.Random.nextBoolean) t._2 else t._1)
}

def zipAndMix[L <: HList, Z <: HList](h1: L, h2: L)(implicit
  zipper: Zip.Aux[L :: L :: HNil, Z],
  mapper: Mapper[mix.type, Z]
) = (h1 zip h2) map mix

现在假设您在问题中定义了 h1h2,您可以这样写:

Now assuming you have h1 and h2 defined as in the question, you can write this:

scala> zipAndMix(h1, h2)
res0: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 5 :: b :: HNil

scala> zipAndMix(h1, h2)
res1: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 6 :: a :: HNil

scala> zipAndMix(h1, h2)
res2: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 5 :: a :: HNil

等等.这将适用于 2.0.0-M1 或最新快照,尽管(正如我在上面的评论中指出的那样)您可能会在 此错误已修复.

And so on. This will work in either 2.0.0-M1 or the latest snapshot, although (as I've noted in a comment above) you may run into confusing issues on the way before this bug was fixed.

这篇关于压缩 HList 的推断函数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 05:15