Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.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_Polymorphism_Implicit - Fatal编程技术网

scala中的嵌套多态性

scala中的嵌套多态性,scala,polymorphism,implicit,Scala,Polymorphism,Implicit,我需要一个具有方法的隐式类,该方法允许我合并任何不可变的映射类型解决问题的关键是不要试图立即推断一个映射类型。即使是如此简单的事情也会使类型推断失败: class Foo[B, A <: Map[String, B]](val a: A) new Foo(Map("foo" -> 42)) inferred type arguments [Nothing,scala.collection.immutable.Map[String,Int]] do not con

我需要一个具有方法的隐式类,该方法允许我合并任何不可变的映射类型解决问题的关键是不要试图立即推断一个映射类型。即使是如此简单的事情也会使类型推断失败:

class Foo[B, A <: Map[String, B]](val a: A)
new Foo(Map("foo" -> 42))

inferred type arguments [Nothing,scala.collection.immutable.Map[String,Int]] do not conform to value 's type parameter bounds [B,A <: Map[String,B]]

type mismatch;
 found   : scala.collection.immutable.Map[String,Int]
 required: A
现在让我们看看你的问题。您的可组合特性通常会被类型类替换,这样您就不必在需要组合的每个类型上扩展Combinable。您可以隐式地为您需要的每种类型提供可组合的。这完全是可选的,如果你愿意,你可以选择坚持你的特质

trait Combinable[A] {
  def combine(first: A, second: A): A
  def combine(first: A, second: Option[A]): A = second match {
    case Some(a) => combine(first, a)
    case None => first
  }
}

case class Meta(x: Int)
object Meta {
  implicit val combinableInstance: Combinable[Meta] = (first, second) => Meta(first.x + second.x)
}


implicit class CombinableMaps[B : Combinable, A[X] <: Map[String,X]](val m1: A[B]) {
  def mergeMaps(m2: A[B]): A[B] = {  
    m1 ++
    m2.map { case (k,v) => k -> implicitly[Combinable[B]].combine(v,m1.get(k)) }
  }.asInstanceOf[A[B]]
}

import collection.immutable.TreeMap
val m = TreeMap("foo" -> Meta(42), "bar" -> Meta(43))
val m2 = TreeMap("bar" -> Meta(43))
val m3: TreeMap[String,Meta] = m.mergeMaps(m2)

除了@francoisr的建议,你对F-有界多态性B的方法只是好奇:使用这种类型而不是更高级的类型有什么好处吗?我并不是说这更糟糕,我只是想看看是否有这种方法更可取的情况。@francoisr好吧,f-bounds和type类是众所周知的竞争方法,没有普遍的优势。如果您对灵活性感兴趣,那么类型类会更灵活一些。如果你对刚性感兴趣的话,F-界会有点刚性。我的第一个修复只是对OP代码的一个最小修复。请注意我的第二个补丁。我删除了一个实例。@francoisr注意,F-Bound也更脆弱,你可以很容易地打破它。此外,这只是一个“半群*@francoisr”,因此,引入更高类型的类型是一个好主意,因为正如我们所看到的,Map ops(如+)是以这种方式定义的。刚才你用一个类型类另外替换了f-bounded Combinable,我之前的评论是关于这个的。@kmh因为如果a=CC[String,B]那么a=>CC[String,B],CC[String,B]=>a就是a=>a,这样的隐式自动在一个作用域中:def test[a]:Unit={隐式[a=>a]}编译。谢谢@francoisr。。。你们两个都给了我很多好东西要学习,以前从来没有见过特别的多态性或类型类,还有其他东西。我有很多东西要学。非常感谢。
implicit class CombinableMaps[A <: Combinable[A]](val m1: Map[String, A]) {
  def mergeMaps(m2: Map[String, A]): Map[String, A] = {  
    m1 ++
    m2.map { case (k,v) => k -> (v combine m1.get(k)) }
  }.asInstanceOf[Map[String, A]]
}
implicit class CombinableMaps[B <: Combinable[B], A <: Map[String,B]](val m1: A) {
  def mergeMaps(m2: A): A = {  
    m1 ++
    m2.map { case (k,v) => k -> (v combine m1.get(k)) }
  }.asInstanceOf[A]
}
class Foo[B, A <: Map[String, B]](val a: A)
new Foo(Map("foo" -> 42))

inferred type arguments [Nothing,scala.collection.immutable.Map[String,Int]] do not conform to value 's type parameter bounds [B,A <: Map[String,B]]

type mismatch;
 found   : scala.collection.immutable.Map[String,Int]
 required: A
class Foo[B, A[X] <: Map[String, X]](val a: A[B])
new Foo(Map("foo" -> 42))
trait Combinable[A] {
  def combine(first: A, second: A): A
  def combine(first: A, second: Option[A]): A = second match {
    case Some(a) => combine(first, a)
    case None => first
  }
}

case class Meta(x: Int)
object Meta {
  implicit val combinableInstance: Combinable[Meta] = (first, second) => Meta(first.x + second.x)
}


implicit class CombinableMaps[B : Combinable, A[X] <: Map[String,X]](val m1: A[B]) {
  def mergeMaps(m2: A[B]): A[B] = {  
    m1 ++
    m2.map { case (k,v) => k -> implicitly[Combinable[B]].combine(v,m1.get(k)) }
  }.asInstanceOf[A[B]]
}

import collection.immutable.TreeMap
val m = TreeMap("foo" -> Meta(42), "bar" -> Meta(43))
val m2 = TreeMap("bar" -> Meta(43))
val m3: TreeMap[String,Meta] = m.mergeMaps(m2)
implicit class CombinableMaps[B <: Combinable[B], A <: Map[String, B]](val m1: A) {
  def mergeMaps(m2: A): A = {  
    m1 ++
    m2.map { case (k,v) => k -> (v combine m1.get(k)) }
  }.asInstanceOf[A]
}
implicit class CombinableMaps[A, B](val m1: A)(implicit
  ev: A <:< Map[String, B],
  ev1: B <:< Combinable[B]
) {
  def mergeMaps(m2: A): A = {
    m1 ++
      m2.map { case (k,v) => k -> (v combine m1.get(k)) }
  }.asInstanceOf[A]
}
implicit class CombinableMaps[A, B <: Combinable[B]](val m1: A)(implicit
  ev: A <:< Map[String,B]
) {
  def mergeMaps(m2: A): A = {
    m1 ++
      m2.map { case (k,v) => k -> (v combine m1.get(k)) }
  }.asInstanceOf[A]
}
import scala.collection.immutable.MapOps

implicit class CombinableMaps[A, B <: Combinable[B], 
                              CC[K,+V] <: MapOps[K, V, CC, _]](val m1: A)(implicit
  ev0: A => CC[String, B],
  ev2: CC[String, B] => A,
) {
  def mergeMaps(m2: A): A = {
    m1 ++
      m2.map { case (k,v) => k -> (v combine m1.get(k)) }
  }
}
implicit class CombinableMaps[B <: Combinable[B], 
                              CC[K,+V] <: MapOps[K, V, CC, _]
                             ](val m1: CC[String, B]){
  def mergeMaps(m2: CC[String, B]): CC[String, B] = {
    m1 ++
      m2.map { case (k,v) => k -> (v combine m1.get(k)) }
  }
}