Экзистенциальные типы в Scala

Пожалуйста, найдите ниже короткий пример, который меня озадачивает.

Я должен признать, что у меня есть некоторые трудности с манипулированием экзистенциальными типами в Scala.

Как мне решить строку несоответствия типа 56? предлагающий в порядке тип _$1, в то время как предлагающие имеют тип _$1 ‹: Индивидуальный

Заранее спасибо,

Максим.

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

person maxime.morge    schedule 03.02.2014    source источник
comment
В чем вопрос? Можете ли вы явно указать, что вы не поняли выше.   -  person Jatin    schedule 03.02.2014
comment
Как устранить несоответствие типа в строке 56? Любая идея ?   -  person maxime.morge    schedule 03.02.2014
comment
Можете ли вы прокомментировать свой код, где есть ошибка   -  person Jatin    schedule 03.02.2014
comment
List, который является ковариантным, должен быть предпочтительнее, чем Set, который не является. Поэтому я использую варные предложения: List[Individual] = List[Individual]() и Proposers=proposers.filterNot(p=›p==proposer). Оно работает.   -  person maxime.morge    schedule 03.02.2014
comment
работает - сильное утверждение, все, что вы сделали, это устранили ошибку компиляции. Чтобы действительно работать, он также должен поддерживаться, что означает, что вы должны выйти за рамки простого написания Java с выводом.   -  person Kevin Wright    schedule 03.02.2014
comment
Вероятно, это политический климат сегодняшнего дня, но это кажется ужасно нагруженным вопросом :)   -  person Mysterious Dan    schedule 03.02.2014


Ответы (1)


Этот код грязный. Он плохо отформатирован, в нем смешаны табуляции и пробелы, и он использует изменчивость даже в самых тривиальных местах, где функциональное решение не требует особых размышлений.

Этот код также не будет масштабироваться на международном уровне для стран, где возможны однополые браки.

Работа сверху вниз...

Я подозреваю, что вы никогда не захотите напрямую создавать экземпляр Individual, а только Man или Woman. Таким образом, алгебраический тип данных имеет больше смысла, это делается с помощью подтипов sealed trait и case 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 тоже может быть case-классом, и давайте бросим неуклюжее дублирование параметров класса в vals — это просто бессмысленный шаблон. Это также хорошее время, чтобы переместить вспомогательный конструктор в фабричный метод в сопутствующем объекте:

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? Такие вещи имели смысл в Java до Generics, но не более того. Я все равно оставлю его (пока), чтобы исправить эту реализацию 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 экземпляров. Но это становится немного более продвинутым.

person Kevin Wright    schedule 03.02.2014