如何创建追加函数
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 风格的抽象特征,带有像 prepend、foldLeft 和 empty 这样的基本操作相同类型的集合。基于它们定义 reverse
和 append
非常简单:
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)
}
我正在尝试在 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 风格的抽象特征,带有像 prepend、foldLeft 和 empty 这样的基本操作相同类型的集合。基于它们定义 reverse
和 append
非常简单:
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)
}