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 - Fatal编程技术网

scala:使用隐式为方法的每个参数支持两种不同的类型?

scala:使用隐式为方法的每个参数支持两种不同的类型?,scala,Scala,假设我有一个接受大量参数的方法,每个参数可以是字符串或Seq[String]。在该方法中,我希望每个参数的值如果是字符串,则仅为该值;如果是Seq[String],则为Seq上的mkString“”。我知道这里可以使用Left/Right,但我不希望调用方必须包装任何参数 我已经使用implicits强制arg为String或Seq[String],但我不知道如何让arg根据具体情况将其自身还原为String,或者作为标识,或者作为mkString。理想的代码可能如下所示: trait StrO

假设我有一个接受大量参数的方法,每个参数可以是字符串或Seq[String]。在该方法中,我希望每个参数的值如果是字符串,则仅为该值;如果是Seq[String],则为Seq上的mkString“”。我知道这里可以使用Left/Right,但我不希望调用方必须包装任何参数

我已经使用implicits强制arg为String或Seq[String],但我不知道如何让arg根据具体情况将其自身还原为String,或者作为标识,或者作为mkString。理想的代码可能如下所示:

trait StrOrSeqStr[A]

implicit object Str extends StrOrSeqStr[String]
implicit object SeqStr extends StrOrSeqStr[Seq[String]]

def f[A, B](a: A, b: B)(implicit a: StrOrSeqStr[A], implicit b: StrOrSeqStr[B]) {
  val aIn: String = a
  val bIn: String = b // converts strings to themselves, seq strings as _ mkString " "
}

// both should work
f(Seq("1"), "2")
f("1", Seq("2", "3"))

有什么建议吗?谢谢

如果我错了,请纠正我,但据我所知,您只需要隐式地将
String
转换为
Seq[String]
。这个简单的隐式转换应该可以做到这一点:

implicit def stringToSeqString(s: String) = Seq(s)

def f(a: Seq[String], b: Seq[String]) {
  val (aIn, bIn) = (a mkString " ", b mkString " ")
  // ...
}

f(Seq("1"), "2")
f("1", Seq("2", "3"))

如果我错了,请纠正我,但据我所知,您只需要隐式地将
String
转换为
Seq[String]
。这个简单的隐式转换应该可以做到这一点:

implicit def stringToSeqString(s: String) = Seq(s)

def f(a: Seq[String], b: Seq[String]) {
  val (aIn, bIn) = (a mkString " ", b mkString " ")
  // ...
}

f(Seq("1"), "2")
f("1", Seq("2", "3"))

据我所知,您试图使用上下文边界来赋予函数
f
一些可以被视为
String
或可以转换为它的内容。除了我的其他答案之外,我还想添加其他使用类型类的解决方案。它更复杂,所以我可以建议你使用简单的隐式转换,我在另一个答案中描述过,如果它解决了你的问题

出于演示目的,我将
StrOrSeqStr
重命名为
displaybable
,并使其更通用,这样它不仅适用于
String
Seq[String]
,而且适用于任何其他类型,如果类型参数
T
也具有
displaybable
(它实际上可以与您想要的任何类一起工作-您只需要提供合适的隐式表达式)

首先,您需要定义可显示的

trait Displayable[T] {
  def getString(target: T): String
}

object Displayable {
  implicit object StringDisplayable extends Displayable[String] {
    def getString(str: String) = str
  }

  implicit object DateDisplayable extends Displayable[Date] {
    val dateFormat = new SimpleDateFormat("dd.MM.yyyy")
    def getString(date: Date) = dateFormat format date
  }

  implicit def seqDisplayable[T: Displayable] = new Displayable[Seq[T]] {
    def getString(seq: Seq[T]) = seq map implicitly[Displayable[T]].getString mkString " "
  }
}
正如您所看到的,我在companion对象中收集了所有相关的隐式,因此它们总是可用的,并且不需要显式导入(便于将来使用)

这里有趣的方法是
seqdisplaybable
——它要求
T
也具有
displaybable
(这也使得它具有递归性——例如,
Seq[Seq[Date]]
也具有
可显示性
)。我还为
String
Date
创建了特殊规则。正如您所见,它非常严格,允许
String
Date
Seq[String],
Seq[Date]
Seq[Seq[String]
Seq[Seq[String]]
,等等。如果要允许所有其他对象,可以添加如下内容:

implicit def anythingDisplayable[T] = new Displayable[T] {
  def getString(anything: T) = anything toString
}
现在是
f
功能:

def f[A : Displayable, B : Displayable](a: A, b: B) {
  val aIn = implicitly[Displayable[A]].getString(a)
  val bIn = implicitly[Displayable[B]].getString(b)
  // ...
}
所以我需要证据:对于
A
B
应该存在一些
displayible
,然后我使用这些
displayible
将它们转换为
String
。如果你想进一步简化它,你可以创建从
dislplayible
String
的隐式转换:

implicit def displayableToString[T : Displayable](target: T) =
      implicitly[Displayable[T]].getString(target)

def f[A : Displayable, B : Displayable](a: A, b: B) {
  val aIn: String = a
  val bIn: String = b
  //...
}
以下是使用示例:

f(Seq("1"), "2")
f("1", Seq("2", "3"))
f(new Date, Seq("10", "3"))
f(new Date, Seq(Seq("10", "11"), Seq("3", "4")))
f(Seq(new Date, new Date(12345)), "1")

希望这有帮助。

据我所知,您试图使用上下文边界,以便为函数
f
提供一些可以被视为
字符串或可以转换为字符串的内容。除了我的其他答案之外,我还想添加其他使用类型类的解决方案。这更复杂,因此我建议您使用简单的隐式conversion,我在另一个答案中描述过,如果它解决了您的问题

出于演示目的,我将
StrOrSeqStr
重命名为
displaybable
,并使其更通用,这样它不仅适用于
String
Seq[String]
,而且适用于任何其他类型,如果类型参数
T
也具有
displaybable
(它实际上可以与您想要的任何类一起工作-您只需要提供合适的隐式表达式)

首先,您需要定义可显示的

trait Displayable[T] {
  def getString(target: T): String
}

object Displayable {
  implicit object StringDisplayable extends Displayable[String] {
    def getString(str: String) = str
  }

  implicit object DateDisplayable extends Displayable[Date] {
    val dateFormat = new SimpleDateFormat("dd.MM.yyyy")
    def getString(date: Date) = dateFormat format date
  }

  implicit def seqDisplayable[T: Displayable] = new Displayable[Seq[T]] {
    def getString(seq: Seq[T]) = seq map implicitly[Displayable[T]].getString mkString " "
  }
}
正如您所看到的,我在companion对象中收集了所有相关的隐式,因此它们总是可用的,并且不需要显式导入(便于将来使用)

这里有趣的方法是
seqdisplaybable
——它要求
T
也具有
displaybable
(这也使得它具有递归性——例如,
Seq[Seq[Date]]
也具有
可显示性
)。我还为
String
Date
创建了特殊规则。正如您所见,它非常严格,允许
String
Date
Seq[String],
Seq[Date]
Seq[Seq[String]
Seq[Seq[String]]
,等等。如果要允许所有其他对象,可以添加如下内容:

implicit def anythingDisplayable[T] = new Displayable[T] {
  def getString(anything: T) = anything toString
}
现在是
f
功能:

def f[A : Displayable, B : Displayable](a: A, b: B) {
  val aIn = implicitly[Displayable[A]].getString(a)
  val bIn = implicitly[Displayable[B]].getString(b)
  // ...
}
所以我需要证据:对于
A
B
应该存在一些
displayible
,然后我使用这些
displayible
将它们转换为
String
。如果你想进一步简化它,你可以创建从
dislplayible
String
的隐式转换:

implicit def displayableToString[T : Displayable](target: T) =
      implicitly[Displayable[T]].getString(target)

def f[A : Displayable, B : Displayable](a: A, b: B) {
  val aIn: String = a
  val bIn: String = b
  //...
}
以下是使用示例:

f(Seq("1"), "2")
f("1", Seq("2", "3"))
f(new Date, Seq("10", "3"))
f(new Date, Seq(Seq("10", "11"), Seq("3", "4")))
f(Seq(new Date, new Date(12345)), "1")
希望这有帮助。

非常接近,非常接近

trait StrOrSeqStr[A] {
  def mkString(x: A): String
}

implicit object Str extends StrOrSeqStr[String] { def mkString(s: String) = s }
implicit object SeqStr extends StrOrSeqStr[Seq[String]] {
    def mkString(s: Seq[String]) = s mkString " "
}

def f[A, B](a: A, b: B)(implicit evA: StrOrSeqStr[A], evB: StrOrSeqStr[B]) {
  implicit def fromSeqString(s: Seq[String]): String = s mkString ""
  val aIn: String = evA mkString a
  val bIn: String = evB mkString b
}

// both should work
f(Seq("1"), "2")
f("1", Seq("2", "3"))
接近,非常接近

trait StrOrSeqStr[A] {
  def mkString(x: A): String
}

implicit object Str extends StrOrSeqStr[String] { def mkString(s: String) = s }
implicit object SeqStr extends StrOrSeqStr[Seq[String]] {
    def mkString(s: Seq[String]) = s mkString " "
}

def f[A, B](a: A, b: B)(implicit evA: StrOrSeqStr[A], evB: StrOrSeqStr[B]) {
  implicit def fromSeqString(s: Seq[String]): String = s mkString ""
  val aIn: String = evA mkString a
  val bIn: String = evB mkString b
}

// both should work
f(Seq("1"), "2")
f("1", Seq("2", "3"))

…或反之亦然-seq2String方法…或反之亦然-seq2String方法。