简体   繁体   English

Scala中的现有类型

[英]Existential types in Scala

Please find below a short example which puzzles me. 请在下面找到一个使我感到困惑的简短示例。

I must concede that I have some difficulties to manipulate existential types in Scala. 我必须承认,在Scala中操纵存在类型存在一些困难。

How should I solve the type mismatch line 56 ? 我应该如何解决类型不匹配的第56行? proposer is OK type _$1 while proposers is of type _$1 <: Individual 提议者可以__1类型,而提议者可以__1类型<:个人

Thanks in advance, 提前致谢,

Maxime. 马克西姆

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)
  }
}

This code is messy. 这段代码很乱。 It's poorly formatted, it mixes tabs and spaces, and it uses mutability even in the most trivial of places where a functional solution requires little thought. 它的格式不正确,混合了制表符和空格,即使在功能解决方案几乎不需要思考的最琐碎的地方,它也使用可变性。

This code also won't scale internationally to countries where same-sex marriage is a possibility. 该法规也无法在国际上推广到可能发生同性婚姻的国家。

Working from the top down... 从上到下工作...

I suspect you'll never want to directly instantiate an Individual , only ever a Man or a Woman . 我怀疑您永远都不想直接实例化一个Individual ,只是一个Man或一个Woman So a algebraic data type makes more sense, this is done with a sealed trait and case class subtypes. 因此,代数数据类型更有意义,这是通过sealed traitcase class子类型完成的。

I'll also drop the preferred property, as it can lead to circular references. 我还将删除preferred属性,因为它可能导致循环引用。 Dealing with this in immutable data is beyond the level I'm willing to go in this answer. 处理不可变数据超出了我在这个答案中愿意达到的水平。

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 can also be a case class, and let's drop the clumsy duplication of class parameters into vals - it's just pointless boilerplate. Marriage也可以是一个案例类,让我们将类参数的笨拙重复放入val中-这只是毫无意义的样板。 This is also a good time to move the auxiliary constructor to a factory method in the companion object: 这也是将辅助构造函数移动到伴随对象中的工厂方法的好时机:

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 is almost pointless, an entire class just to wrap a List ? Matching几乎没有意义,整个类只是包装一个List This kind of thing made sense in pre-Generics Java, but not any more. 在前泛型Java中,这种事情很有意义,但现在已经不复存在了。 I'll keep it anyway (for now) so I can fix up that toString implementation, which is painfully mutable and uses return for no good reason: 我仍将保留它(暂时),以便我可以修复该toString实现,该实现很痛苦地易变,并且没有充分的理由使用return

case class Matching(){
  private var list: List[Marriage] = Nil
  def add(m: Marriage): Unit = { list ::= m }
  override def toString() = list.mkString(" ")
}

Finally, the "meat" of the problem. 最后是“肉”的问题。 Comments are inline, but you'll note that I don't need (or use) Matching . 评论是内联的,但您会注意到我不需要(或使用) Matching It's replaced in its entirety by the final println 最后的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 " ")
  }
}

There's more that can be done here, way more. 还有更多可以在这里完成的方法。 What of same-sex relationships? 什么是同性关系? What if two or more people share the same preference? 如果两个或两个以上的人拥有相同的偏好怎么办? What if someone has no preference? 如果某人没有偏好怎么办?

I could also encode the type of someone's preference into Individual instances. 我还可以将某人的偏好类型编码为Individual实例。 But that's getting a bit more advanced. 但这已经变得更加先进。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM