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
如何在scala中创建尊重隐式转换的内联函数?_Scala_Generics_Type Inference_Implicit Conversion_Implicit - Fatal编程技术网

如何在scala中创建尊重隐式转换的内联函数?

如何在scala中创建尊重隐式转换的内联函数?,scala,generics,type-inference,implicit-conversion,implicit,Scala,Generics,Type Inference,Implicit Conversion,Implicit,以以下代码为例: 对象测试6{ def main(参数:数组[字符串]):单位={ val a=新a //工作 TakesTuple(tupleMaker(a,a)) //不起作用,因为a变成了ArrowAssoc[a]的实例,而不是ArrowAssoc[B] TakesBuple(a->a) } 甲级 B类 隐式定义atob(a:a):B=新B def tupleMaker[X,Y](X:X,Y:Y):(X,Y)=(X,Y) def takesBTuple(b:(b,b)):单位=printl

以以下代码为例:

对象测试6{
def main(参数:数组[字符串]):单位={
val a=新a
//工作
TakesTuple(tupleMaker(a,a))
//不起作用,因为a变成了ArrowAssoc[a]的实例,而不是ArrowAssoc[B]
TakesBuple(a->a)
}
甲级
B类
隐式定义atob(a:a):B=新B
def tupleMaker[X,Y](X:X,Y:Y):(X,Y)=(X,Y)
def takesBTuple(b:(b,b)):单位=println(“take”)
}

如何使用内联函数获得TupleMaker的行为(特别是w.r.t.隐式转换)?我可以修改A类和B类,并使用任何中缀运算符(不必是现有的)如果这有助于解决问题。

您可以再添加一个转换

implicit def tupleToTuple(a: (A, A)): (B, B) = (atob(a._1), atob(a._2))
更通用的解决方案是

class A
class A1
class B

implicit def atob(a: A): B = new B
implicit def a1tob(a: A1): B = new B

implicit def tupleToTuple[T, X1, Y1, X, Y](t: (X, Y))(implicit 
  ev: T <:< (X1, Y1), 
  ev1: X => X1, 
  ev2: Y => Y1
): T = (t._1, t._2)


val a = new A
val a1 = new A1

takesBTuple(a -> a) // compiles
takesBTuple(a1 -> a1) // compiles
takesBTuple(a -> a1) // compiles 

不起作用,因为首先推断出
X
(为
A
)。因此
ev:T您可以再添加一个转换

implicit def tupleToTuple(a: (A, A)): (B, B) = (atob(a._1), atob(a._2))
更通用的解决方案是

class A
class A1
class B

implicit def atob(a: A): B = new B
implicit def a1tob(a: A1): B = new B

implicit def tupleToTuple[T, X1, Y1, X, Y](t: (X, Y))(implicit 
  ev: T <:< (X1, Y1), 
  ev1: X => X1, 
  ev2: Y => Y1
): T = (t._1, t._2)


val a = new A
val a1 = new A1

takesBTuple(a -> a) // compiles
takesBTuple(a1 -> a1) // compiles
takesBTuple(a -> a1) // compiles 

不起作用,因为首先推断出
X
(为
A
)。因此,解决这个问题的简单方法是

takesBTuple((a:B) -> a)
否则,您可以定义一个trait
ConvertibleToB
,它将
->
作为一个方法,然后这就可以工作了

val a = new A
val aa = new AA
//all of these work
takesBTuple(tupleMaker(a, a))
takesBTuple(a -> a)
takesBTuple(aa -> a)
takesBTuple(a -> aa)
takesConvertibleToBTuple(a -> a)
takesConvertibleToBTuple(a -> aa)

//Just for demonstration
def takesConvertibleToBTuple(t: (ConvertibleToB, ConvertibleToB)): Unit = println("took " + t)
需要导入的唯一隐式def是
makeB
。我不知道这是否是您想要的,或者它是否对您实用,尤其是如果您不想将
(A,AA)
类型的元组转换为
(B,B)


链接到Scastie:

解决这个问题的简单方法是

takesBTuple((a:B) -> a)
否则,您可以定义一个trait
ConvertibleToB
,它将
->
作为一个方法,然后这就可以工作了

val a = new A
val aa = new AA
//all of these work
takesBTuple(tupleMaker(a, a))
takesBTuple(a -> a)
takesBTuple(aa -> a)
takesBTuple(a -> aa)
takesConvertibleToBTuple(a -> a)
takesConvertibleToBTuple(a -> aa)

//Just for demonstration
def takesConvertibleToBTuple(t: (ConvertibleToB, ConvertibleToB)): Unit = println("took " + t)
需要导入的唯一隐式def是
makeB
。我不知道这是否是您想要的,或者它是否对您实用,尤其是如果您不想将
(A,AA)
类型的元组转换为
(B,B)


链接到Scastie:

我可以定义这个隐式。但是,让我们假设有多个可能的A类具有到B的隐式转换。为了使其工作,相关的隐式转换必须在范围内。但是,由于它们是元组,这些隐式转换必须在我无法修改的元组类中定义。如果我错了,请告诉我。@GUIpsp“这些隐式转换必须在元组类“否”中定义。您可以将它们导入到当前范围。虽然这是真的,但如果有多个A类,我要么单独导入每个转换,要么将它们捆绑在一起并一次性导入。第一个是不可接受的,因为它太冗长了。第二个在我的例子中是不可接受的,因为类是自动生成的:我可以修改生成,但不能创建它们的索引。此回复是在更新之前编写的更新后的解决方案似乎可以工作,谢谢。然而,我试图准确地理解它是如何工作的:我知道ev1 ev2参数会自动填充相应的隐式函数,然而,ev参数的作用是什么?@GUIpsp好的,事情是更简单的
implicit def tupleToTuple[X,Y,X1,Y1](t:(X,Y))(隐式ev1:X=>X1,ev2:Y=>Y1):(X1,Y1)(t._1,t._2)
不起作用,因为首先推断出
X
(即
A
).So
ev:T我可以定义这个隐式转换。但是,让我们假设有多个可能的A类具有到B的隐式转换。为了使其工作,相关的隐式转换必须在范围内。但是,由于它们是元组,这些隐式转换必须在我无法修改的元组类中定义fy.如果我错了,请告诉我。@GUIpsp“这些隐式转换必须在tuple类中定义”不可以。您可以将它们导入到当前作用域。尽管如此,如果有多个A类,我必须单独导入每个转换,或者将它们捆绑在一起并一次性导入。第一个是不可接受的,因为它太冗长。第二个是不可接受的,因为在我的情况下,类是自动生成的ted:我可以修改生成,但是我不能创建它们的索引。这个回复是在更新之前写的。更新的解决方案似乎可以工作,谢谢。但是,我试图准确地理解它是如何工作的:我知道ev1 ev2参数会自动填充相应的隐式函数,但是,ev pa的作用是什么rameter?@GUIpsp好吧,问题是更简单的
隐式def tupleToTuple[X,Y,X1,Y1](t:(X,Y))(隐式ev1:X=>X1,ev2:Y=>Y1):(X1,Y1)=(t.。_1,t._2)
不起作用,因为
X
首先被推断出来(成为
A
)。所以
ev:t