簡體   English   中英

上下文綁定到varargs

[英]Context bound for varargs

幾天前,我開始學習Cats,並且想為Map[String, _: Show]實現方法appendOptional

我從以下想法開始:

def appendOptional[T: Show](to: Map[String, String], values: (String, Option[T])*): Map[String, String] = 
    values.foldLeft(values) {
        case (collector, (key, Some(value))) => 
            collector + (key -> implicitly[Show[T]].show(value)) 
        case (collector, _) => collector
    }

並像這樣使用它:

def createProps(initial: Map[String, String], name: Option[String], age: Option[Int])

val initial = Map("one" -> "one", "two" -> "two")
val props = appendOptional(initial, "name" -> name, "age" -> age)

我知道這種方法非常幼稚和直接,因為implicitly[Show[T]].show(value)實際上會查找Show[Any]

另外,我有一個想法可以接受帶有上下文綁定的HList ,但是我還沒有找到任何這樣的例子。

另一種變種是創建許多重載方法(就像在許多天秤中一樣):

def appendOptional[T1: Show, T2: Show](to: Map[String, String], v1: (String, Option[T1], v2: (String, Option[T2])))

問題 :有沒有一種方法可以為varargs函數定義上下文綁定?

嚴格來說,第一種定義邊界的正確方法;第二種定義邊界的正確方法。 varargs並不意味着參數的類型有所不同,只是它們的數量有所不同。

使用各種類型來實現所需功能的方法涉及更多,並且需要將Show實例與值打包在一起。 例如

case class HasShow[A](x: A)(implicit val ev: Show[A])

def appendOptional(to: Map[String, String], values: (String, Option[HasShow[_]])*): Map[String, String] =     
    values.foldLeft(values) {
        // value.ev.show(value.x)) can be extracted into a method on HasShow as well
        case (collector, (key, Some(value: HasShow[a]))) => 
            collector + (key -> value.ev.show(value.x)) 
        case (collector, _) => collector
    }

val props = appendOptional(initial, "name" -> name.map(HasShow(_)), "age" -> age.map(HasShow(_)))

您可以對HasShow進行一些更多的隱式轉換,以簡化調用站點,但是通過這種方式,您可以看到發生了什么。

對於這種特定情況,我認為將有一個更好,更簡單的解決方案

implicit class MapOp(self: Map[String, String]) extends AnyVal {
    def appendOptional[A: Show](key: String, value: Option[A]) =  
        value.fold(self)(x => self + (key -> Show.show(x)))
}

val props = initial.appendOptional("name", name).appendOptional("age", age)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM