使用类型参数的类型参数作为 Scala 中的字段类型 [英] Use type parameter's type argument as field type in Scala

查看:28
本文介绍了使用类型参数的类型参数作为 Scala 中的字段类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以跟进 Scala 中的递归类型定义,我现在有了我的类型CatenableListFromQueue的数据承载结构:

So following up on Recursive type definition in Scala, I now have my type for the data-bearing structure of 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 本身是一个类型类,即它只定义了一些通用数据承载结构的方法:

now the intended value for the parameter Q is, naturally, a queue. My Queue itself is a type class, i.e. it only defines the methods for some generic data-bearing structure:

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, e.g.

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 的数据承载结构,<代码>队列#Q:

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:

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

  type CL = CatList[queue#Q, E]

因此,在我的理想世界中,该类获得了一个 Queue 实例,即队列操作在某些结构上的实现(此处:Queue#Q),并且在turn 创建并处理实际元素的 CatList 和包含更多 CatLists 的 Queue#Qs.

So in my ideal world the class gets an instance of Queue, i.e. 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#Qs containing further CatLists.

问题是,我似乎无法想出一种在 Scala 中编写代码的方法;在 Haskell 中,这似乎很简单:

The problem is, I cannot seem to come up with a way to code that in Scala; in Haskell, it seems as trivial as:

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

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

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

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.

推荐答案

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

Well, following Haskell's approach was the right way:

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 一个 trait,稍后将它与 QBS 的特定类型一起使用:

So we keep the CatenableListFromQueue a trait, and use it later with a specific type for QBS:

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

这样,一切都编译得很好,而且似乎运行良好.

This way, it all compiles just fine, and seems to work well.

这篇关于使用类型参数的类型参数作为 Scala 中的字段类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆