在Scala中使用type参数的类型参数作为字段类型

时间:2016-03-11 18:12:51

标签: scala types

因此关注Recursive type definition in Scala,我现在拥有CatenableListFromQueue数据承载结构的类型:

object CatenableListFromQueue {

  sealed trait CatList[+Q, +E]

  object Empty extends CatList[Nothing, Nothing]

  case class C[Q[_], E](x: E, q: Q[CatList[Q, E]]) extends CatList[Q, E]
}

现在参数Q的预期值自然是队列。我的Queue本身是一个类型类,即它只定义了一些通用数据承载结构的方法:

trait Queue[E, Q] {

  def empty: Q

  def isEmpty: Q => Boolean

  def snoc: (Q, E) => Q

  def head: Q => E

  def tail: Q => Q
}

对我来说似乎工作得很好,例如

class BatchedQueue[E] extends Queue[E, (List[E], List[E])] {
  override def empty: (List[E], List[E]) = (Nil, Nil)

  override def isEmpty: ((List[E], List[E])) => Boolean = {
    case (Nil, _) => true
    case _ => false
  }

  val checkf: (List[E], List[E]) => (List[E], List[E]) = {
    case (Nil, r) => (r.reverse, Nil)
    case q => q
  }

  override def snoc: ((List[E], List[E]), E) => (List[E], List[E]) = {
    case ((f, r), x) => checkf(f, x :: r)
  }

  override def tail: ((List[E], List[E])) => (List[E], List[E]) = {
    case (Nil, _) => throw new IllegalStateException("tail called on an empty queue")
    case ((_ :: f), r) => checkf(f, r)
  }

  override def head: ((List[E], List[E])) => E = {
    case (Nil, _) => throw new IllegalStateException("head called on an empty queue")
    case ((x :: _), _) => x
  }
}

在我需要创建CatenableListFromQueue之前,一切都进展顺利,Queue包含前一个问题的数据结构,其中包含Queue#Qclass CatenableListFromQueue[E, CL, Q](queue: Queue[E, Q]) extends CatenableList[E] { type CL = CatList[queue#Q, E] 的数据承载结构:< / p>

Queue

因此,在我的理想世界中,类获取Queue#Q的实例,即在某个结构上执行队列操作(此处为:CatList),然后创建并处理{{1}实际元素和Queue#Q包含更多CatList s。

问题是,我似乎无法想出一种在Scala中编写代码的方法;在Haskell中,它似乎微不足道:

data CatList q a = E | C a (q (CatList q a))

instance Queue q => CatenableList (CatList q) where
   -- methods

但是在Scala中我无法想出任何编码相同的方法,因为我的Queue要求数据承载结构作为参数,而数据承载自然包含它在这种情况下包含更多数据的元素 - 相同类型的结构。

1 个答案:

答案 0 :(得分:0)

好吧,遵循Haskell的方法是正确的方法:

object CatenableListFromQueue {

  sealed trait CatList[+Q[_], +E]

  object Empty extends CatList[Nothing, Nothing]

  case class C[Q[_], E](x: E, q: Q[Susp[CatList[Q, E]]]) extends CatList[Q, E]
}

trait CatenableListFromQueue[E, QBS[_]] extends CatenableList[E, CatList[QBS, E]] {

  type Q = Queue[Susp[CatList[QBS, E]], QBS[Susp[CatList[QBS, E]]]]

  def q: Q

  type CL = CatList[QBS, E]

  def just(e: E): CL = C(e, q.empty)

  // etc.

因此我们保留CatenableListFromQueue特征,稍后将其用于QBS的特定类型:

new CatenableListFromQueue[Int, HoodMelvilleQueue.Repr] {
  val q = new HoodMelvilleQueue[Susp[CL]]
}

这样,它编写得很好,似乎运行良好。