Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何将两个元组与兼容类型组合?_Scala_Tuples_Shapeless_Dotty_Scala 3 - Fatal编程技术网

Scala 如何将两个元组与兼容类型组合?

Scala 如何将两个元组与兼容类型组合?,scala,tuples,shapeless,dotty,scala-3,Scala,Tuples,Shapeless,Dotty,Scala 3,假设我有两个元组,第一个是类型为(V1,V2,…,Vn)的值元组 第二个是类型为(V1=>V1,V2=>V2,…,Vn=>Vn)的函数元组 现在我想将两个元组组合为(f1(v1),v2(v2),…,fn(vn)),类型为(v1,v2,…,vn) 我不知道如何在scala 3.0(即dotty)中实现这一点 编辑:我查看了Shapess的源代码,得到了一个(部分工作)解决方案: scala> trait Zip[V <: Tuple, F <: Tuple]{ type R &l

假设我有两个元组,第一个是类型为
(V1,V2,…,Vn)
的值元组

第二个是类型为
(V1=>V1,V2=>V2,…,Vn=>Vn)
的函数元组

现在我想将两个元组组合为
(f1(v1),v2(v2),…,fn(vn))
,类型为
(v1,v2,…,vn)

我不知道如何在scala 3.0(即dotty)中实现这一点

编辑:我查看了Shapess的源代码,得到了一个(部分工作)解决方案:

scala> trait Zip[V <: Tuple, F <: Tuple]{ type R <: Tuple; def apply(v: V, f: F): R }

scala> given Zip[Unit, Unit]{ type R = Unit; def apply(v: Unit, f: Unit): Unit = () }

scala> given [Hv, Hr, V <: Tuple, F <: Tuple](given z: Zip[V, F]): Zip[Hv *: V, (Hv => Hr) *: F] = new Zip {
     |   type R = Hr *: z.R
     |   def apply(v: Hv *: V, f: (Hv => Hr) *: F): R = {
     |     f.head(v.head) *: z.apply(v.tail, f.tail)
     |   }
     | }

scala> val values = (1, 2.0, "3")
val values: (Int, Double, String) = (1,2.0,3)

scala> val funs = ((i: Int) => 2 * i, (f: Double) => 2 * f, (s: String) => s * 2)
val funs: (Int => Int, Double => Double, String => String) = ..

scala> def apply[V <: Tuple, F <: Tuple](v: V, f: F)(given z: Zip[V, F]): z.R = z.apply(v, f)
def apply[V <: Tuple, F <: Tuple](v: V, f: F)(given z: Zip[V, F]): z.R

scala> apply(values, funs)
val res0:
  Zip[(Int, Double, String), (Int => Int, Double => Double, String => String)]#R = (2,4.0,33)

scala> val res: (Int, Double, String) = apply(values, funs)
1 |val res: (Int, Double, String) = apply(values, funs)
  |                                 ^^^^^^^^^^^^^^^^^^^
  |Found:    ?1.R
  |Required: (Int, Double, String)
  |
  |where:    ?1 is an unknown value of type Zip[(Int, Double, String), (Int => Int, Double => Double, String => String)]
scala>trait-Zip[V-val值=(1,2.0,“3”)
val值:(Int,Double,String)=(1,2.0,3)
scala>valfuns=((i:Int)=>2*i,(f:Double)=>2*f,(s:String)=>s*2)
val funs:(Int=>Int,Double=>Double,String=>String)=。。
scala>def应用[V字符串)]#R=(2,4.0,33)
scala>val res:(Int,Double,String)=应用(值,funs)
1 | val res:(Int,Double,String)=应用(值,funs)
|                                 ^^^^^^^^^^^^^^^^^^^
|发现:?1.R
|必需:(整数、双精度、字符串)
|
|其中:?1是Zip[(Int,Double,String),(Int=>Int,Double=>Double,String=>String]类型的未知值

我不知道为什么返回的
apply
方法会丢失它的类型。

这似乎是个好办法

val res = List(Range(0, values.productArity).map(n => {
  val arg = values.productElement(n)
  val f = funs.productElement(n).asInstanceOf[(arg.type) => arg.type]
  f.apply(arg)
})).map {
  case Vector(a, b, c) => Tuple3(a, b, c)
}.head

例如,来自Shapeble的zipApply将保持类型安全

import shapeless.syntax.std.tuple._

val values = (1, 2.0, "3")
val funs = ((i: Int) => 2 * i, (f: Double) => 2 * f, (s: String) => s * 2)
funs zipApply values
输出

res0: (Int, Double, String) = (2,4.0,33)
但是,尝试使用
val值=(“1”、“2.0”、“3”)
会产生编译时错误

为什么apply方法的返回会丢失其类型

这是因为您丢失了类型细化(这种行为在Scala2和Dotty中类似)

代码

given [Hv, Hr, V <: Tuple, F <: Tuple](given z: Zip[V, F]): Zip[Hv *: V, (Hv => Hr) *: F] = new Zip {
  ...

在0.21.0-RC1中测试。

谢谢。我不确定dotty中是否有任何简单的解决方案(即仅使用stdlib)。如果像
values.zip(funs.map(t=>t.\u 2(t.\u 1))
这样的东西起作用就好了,但dotty无法推断
t
的类型(有意义,因为它是多态的。)@JörgWMittag我在我的问题中添加了一个部分工作的解决方案,你能帮助我为什么该解决方案丢失了返回类型吗。
given [Hv, Hr, V <: Tuple, F <: Tuple](given z: Zip[V, F]): Zip[Hv *: V, (Hv => Hr) *: F] = new Zip {
  ...
given [Hv, Hr, V <: Tuple, F <: Tuple](given z: Zip[V, F]): (Zip[Hv *: V, (Hv => Hr) *: F] { type R = Hr *: z.R }) = new Zip[Hv *: V, (Hv => Hr) *: F] {
  ...
given [Hv, Hr, V <: Tuple, F <: Tuple](given z: Zip[V, F]): Zip.Aux[Hv *: V, (Hv => Hr) *: F, Hr *: z.R] = new Zip[Hv *: V, (Hv => Hr) *: F] {
  ...