如何创建追加函数

How to create an append function

我正在尝试在 Scala 上创建这个函数,但我不太确定我的做法是否正确。我想我完全迷失了。我需要帮助。

函数append(alist1, alist2),其中alist1和alist2是两个相同类型的类列表集合。

结果应该是一个新的类似列表的集合(与 alist1 和 alist2 具有相同的类型),其中包含 alist1 的元素,后跟 alist2 的元素按顺序排列。 即,在链表上,append(alist1, alist2) 的行为应该类似于 alist1 ++ alist2.

这是我目前所拥有的

            def append [B :> A ]( alist1 : ListLike [B], alist2:ListLike[B]): ListLike [B] = (alist1,alist2) match {
case Nil => Nil
case hd1::tl1 = > hd1 :: tl1.append ( alist1) 
case hd2 ::tl2 => hd2 :: tl2.append(alist2)
        }

这是在 SCALA 中。

你已经在结构上声明了一些方法(isEmpty、cons、head、tail),使用它们我会这样写:

trait Appendable[A]{
  def head: A = ???
  def tail: Appendable[A] = ???
  def isEmpty: Boolean = ???
  def reverse: Appendable[A] = ???
}

object Appendable{
  def cons[A](a: A, appendable: Appendable[A]): Appendable[A] = ???

  def append[A](a1: Appendable[A], a2: Appendable[A]) = 
    appendHelper(a1.reverse, a2)

  private def appendHelper[A](a1: Appendable[A], a2: Appendable[A]): Appendable[A] =
    if(a1.isEmpty) a2
    else appendHelper(a1.tail, cons(a1.head, a2))
}

所以想象一下你有一些 scala-collection 风格的抽象特征,带有像 prependfoldLeftempty 这样的基本操作相同类型的集合。基于它们定义 reverseappend 非常简单:

trait ListLike[+E, T[+X] <: ListLike[X, T]] {
  def +:[E1 >: E](x: E1): T[E1]

  def foldLeft[X](z: X)(f: (X, E) => X): X

  def empty: T[E]

  def reverse: T[E] = foldLeft(empty)((list, x) => x +: list)

  def ++[E1 >: E](that: T[E1]): T[E1] = reverse.foldLeft(that)((list, x) => x +: list)
}

让我们介绍一些具体的类型

sealed trait MyList[+E] extends ListLike[E, MyList] {
  def +:[E1 >: E](x: E1): MyList[E1] = MyCons(x, this)

  def empty = MyNil

  def foldLeft[X](z: X)(f: (X, E) => X): X = {
    def go(z: X, lst: MyList[E]): X = lst match {
      case MyNil => z
      case MyCons(x, next) => go(f(z, x), next)
    }
    go(z, this)
  }

  override def toString = foldLeft("MyList(")( _ + _ + ",") + ")"
}

case object MyNil extends MyList[Nothing]

case class MyCons[+E](elem: E, next: MyList[E]) extends MyList[E]

您现在可以验证

(1 +: 2 +: 3 +: MyNil) ++ (4 +: 5 +: MyNil) 

产生与

完全相同的东西(相同类型)
1 +: 2 +: 3 +: 4 +: 5 +: MyNil 

更新: 如果你不能修改你的抽象类型,你仍然可以将移动操作添加到一些保留语法的隐式包装器中:

implicit class ListLikeOps[E, T[+X] <: ListLike[X, T] ](lst: ListLike[E, T]){
  def ++[E1 >: E](that: T[E1]): T[E1] = lst.reverse.foldLeft(that)((list, x) => x +: list)
}