简体   繁体   English

在Scala中将类型参数的类型参数用作字段类型

[英]Use type parameter's type argument as field type in Scala

So following up on Recursive type definition in Scala , I now have my type for the data-bearing structure of CatenableListFromQueue : 因此,按照Scala中的递归类型定义 ,现在我CatenableListFromQueue的数据承载结构的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]
}

now the intended value for the parameter Q is, naturally, a queue. 现在,参数Q的预期值自然是一个队列。 My Queue itself is a type class, ie it only defines the methods for some generic data-bearing structure: My 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
}

It seems to work just fine for me, eg 对我来说似乎很好用,例如

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

That all was going well until I needed to create a CatenableListFromQueue , which holds a data structure from the previous question with the data-bearing structure of the Queue , Queue#Q : 这一切都进行得很顺利,直到我需要创建一个CatenableListFromQueue ,它拥有与数据承载结构的前一个问题的数据结构QueueQueue#Q

class CatenableListFromQueue[E, CL, Q](queue: Queue[E, Q]) extends CatenableList[E] {

  type CL = CatList[queue#Q, E]

So in my ideal world the class gets an instance of Queue , ie the implementation of the queue operations over some structure (here: Queue#Q ), and in turn creates and handles a CatList of the actual elements and the Queue#Q s containing further CatList s. 因此,在我理想的世界中,该类获取Queue的实例,即,在某种结构(此处为Queue#Q )上实现队列操作,然后依次创建并处理实际元素的CatList和包含以下内容的Queue#Q其他CatList

The problem is, I cannot seem to come up with a way to code that in Scala; 问题是,我似乎无法想出一种在Scala中进行编码的方法。 in Haskell, it seems as trivial as: 在Haskell中,看起来很简单:

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

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

But in Scala I cannot come up with any way to encode the same as my Queue requires that data-bearing structure as a parameter, and the data-bearing naturally contains it elements which in this case contain further data-bearing structures of the same type. 但是在Scala中,我无法提出任何方法来对它进行编码,因为Queue要求将数据承载结构作为参数,并且数据承载自然包含它的元素,在这种情况下,该元素还包含其他相同类型的数据承载结构。

Well, following Haskell's approach was the right way: 好吧,遵循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.

So we keep the CatenableListFromQueue a trait, and use it later with a specific type for QBS : 因此,我们将CatenableListFromQueue保留为特征,以后将其与特定类型的QBS

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

This way, it all compiles just fine, and seems to work well. 这样,所有程序都可以正常编译,并且运行良好。

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

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