Scala中的存在类型

时间:2014-02-03 10:55:11

标签: scala existential-type

请在下面找一个令我困惑的简短例子。

我必须承认,在Scala中操纵存在类型有一些困难。

如何解决类型不匹配线56? 提交者是OK类型_ $ 1,而提议者的类型是_ $ 1&lt ;: Individual

提前致谢,

马克西姆。

class Individual(n: String) {
  protected val name=n
  var preferred: Individual = this
  override def toString(): String=name
}

class Man(n: String) extends Individual(n) { }

class Woman(n: String) extends Individual(n) { }

class Marriage(m: Man, w: Woman){
  private val man=m
  private val woman=w
  def this(w: Woman, m: Man) = this(m,w)
  override def toString(): String = man+"--"+woman
}

class Matching(){
  private var list: List[Marriage] = Nil
  def add(m: Marriage): Unit = { list = m ::list }
  override def toString(): String= {
    var s: String = ""
    for (elm<-list) s=s+elm+" "
    return s
  }
}

object Test{
  protected var male = true

  def main(args: Array[String]): Unit = {
    val al      = new Man("Al")
    val bob     = new Man("Bob")
    val alice   = new Woman("Alice")
    val barbara = new Woman("Barbara")

    al.preferred      = alice
    bob.preferred     = barbara
    alice.preferred   = bob
    barbara.preferred = al

    val men   = Set(al, bob)
    val women = Set(alice, barbara)

    val m = new Matching()
    //var proposers=women

    var proposers: Set[_ <:Individual] = Set[Individual]()
    if (male) proposers = men
    else proposers = women

    while (!proposers.isEmpty) {
      for(proposer <- proposers) {
        val proposer=proposers.head
        if (proposer.isInstanceOf[Man])
          m.add(new Marriage(
            proposer.asInstanceOf[Man],
            proposer.preferred.asInstanceOf[Woman]
          )) 
        else 
          m.add(new Marriage(
            proposer.asInstanceOf[Woman],
            proposer.preferred.asInstanceOf[Man]
          ))
        proposers-=proposer//There is an error here
      } 
    }

    println(m)
  }
}

1 个答案:

答案 0 :(得分:7)

这段代码很乱。它的格式很差,它混合了标签和空格,即使在功能性解决方案几乎不需要考虑的最简单的地方,它也会使用可变性。

此代码也不会在国际范围内扩展到可能存在同性婚姻的国家。

自上而下工作......

我怀疑你从不希望直接实例Individual,只有ManWoman。因此,代数数据类型更有意义,这是通过sealed traitcase class子类型完成的。

我还会删除preferred属性,因为它可能导致循环引用。在不可变数据中处理这个问题超出了我愿意回答的水平。

sealed trait Individual {
  def name: String
  override def toString(): String=name
}

//as it's a case class, `name` becomes a val,
//which implements the abstract `def name` from the trait
case class Man(name: String) extends Individual

case class Woman(name: String) extends Individual

Marriage也可以是一个案例类,让我们把笨拙的类参数重复放到val中 - 它只是毫无意义的样板。这也是将辅助构造函数移动到伴随对象中的工厂方法的好时机:

case class Marriage(man: Man, woman: Woman) {      
  override def toString(): String = man + "--" + woman
}
object Marriage {
  def apply(w: Woman, m: Man) = new Marriage(m,w)
}

Matching几乎没有意义,整个课程只是为了包裹List?这种事情在前Generics Java中是有意义的,但现在不再有了。无论如何我会保留它(现在)所以我可以修复toString实现,这是一个非常可变的并且没有充分理由使用return

case class Matching(){
  private var list: List[Marriage] = Nil
  def add(m: Marriage): Unit = { list ::= m }
  override def toString() = list.mkString(" ")
}
最后,问题的“肉”。评论是内联的,但您会注意到我不需要(或使用)Matching。它被最终的println

全部替换
object Test{
  //better name, and a val (because it never changes)
  protected val menPropose = true

  def main(args: Array[String]): Unit = {

    // `new` not required for case classes
    val al      = Man("Al")
    val bob     = Man("Bob")
    val alice   = Woman("Alice")
    val barbara = Woman("Barbara")

    // remember how preference was removed from `Individual`?
    val mprefs = Map( al -> alice, bob -> barbara )
    val fprefs = Map( alice -> bob, barbara -> al )

    val men   = Set(al, bob)
    val women = Set(alice, barbara)

    // nicely immutable, and using the returned value from if/else
    val proposers = if (menPropose) men else women

    // no while loop, name shadowing, or mutability.
    // just a simple for-comprehension
    val marriages = for(proposer <- proposers) yield {
      //pattern-matching beats `isInstanceOf`... every time
      proposer match {
        case m: Man => Marriage(m, mprefs(m))
        case f: Woman => Marriage(f, fprefs(f))
      }
    }

    println(marriages mkString " ")
  }
}

还有更多可以在这里完成的事情。什么是同性关系?如果两个或更多人共享相同的偏好怎么办?如果有人没有偏好怎么办?

我还可以将某人的偏好类型编码为Individual个实例。但那会更先进。