新集合类的Scala高级类型问题

时间:2016-03-16 18:50:19

标签: scala higher-kinded-types

我正在尝试编写一个同质的元组类型,与scala中的内置元组类型有些相似。

我有以下内容:

trait HomogeneousTupleFactory [H <: HomogeneousTuple[_, H]] {
  def makeHTuple[T] (values: Iterator[T]): HomogeneousTuple[T, H]
}
trait HomogeneousTuple [+T, H <: HomogeneousTuple[_, H]] extends Product {
  def getFactory: HomogeneousTupleFactory[H]
  def map [U] (fcn: T => U): HomogeneousTuple[U, H] = {
    getFactory.makeHTuple(
      this.productIterator.map(t => fcn(t.asInstanceOf[T]))
    )
  }
}

object HTuple2Factory extends HomogeneousTupleFactory[HTuple2[_]] {
  def makeHTuple[T] (values: Iterator[T]): HTuple2[T] = {
    new HTuple2(values.next, values.next)
  }
}
class HTuple2[+T] (t1: T, t2: T) extends Tuple2(t1, t2) 
    with HomogeneousTuple[T, HTuple2[_]] {
  def getFactory = HTuple2Factory
}

我正在努力让HTuple2.map[U]返回HTuple2[U]而不是HomogeneousTuple[U, HTuple2](这是合法且正确的,但不太方便),但我无法得到它起作用。

任何人都有任何线索如何做到这一点?有没有比我正在做的更好的方式?

2 个答案:

答案 0 :(得分:2)

我不得不移动一些东西,但这似乎有效:

def retrieve_data(self, variable):
    start_date = datetime.date.today() - datetime.timedelta(int(self.kwargs['days']))
    invoice_set = InvoiceRecord.objects.filter(sale_date__gte=start_date)
    total = 0
    for invoice in invoice_set:
        for sale in invoice.salesrecord_set.all():
            total += getattr(self, variable)
    return round(total)

基本上你需要HomogeneousTuple中的H类型param是一个更高级的类型,其余的更改都会从中流出。

答案 1 :(得分:0)

我没有足够的时间去发展,但似乎你正在寻找的是

sealed abstract class Nat
final abstract class Z           extends Nat
final abstract class S[n <: Nat] extends Nat

trait Vect[n <: Nat, +A] {
  def map[B](f : A => B) : Vect[n , B]
}

final case object VNil extends Vect[Z, Nothing] {
  def map[B](f : Nothing => B) : Vect[Z, B] = this
}

final case class VCons[n <: Nat, A](head : A, tl : Vect[n, A]) extends Vect[S[n], A] {
  def map[B](f : A => B) : Vect[S[n], B] = VCons[n, B](f(head), tl.map(f))
}

implicit final class ConsOps[A](val self : A) extends AnyVal {
  def +++[n <: Nat](l : Vect[n, A]) : Vect[S[n], A] = VCons(self, l)
}

type _0 = Z
type _1 = S[_0]
type _2 = S[_1]

type Tuple0[A] = Vect[_0, A]
type Tuple1[A] = Vect[_1, A]
type Tuple2[A] = Vect[_2, A]

def inc[n <: Nat](v : Vect[n , Int]) : Vect[n , Int] = v.map((i : Int) => i + 1)

inc(2 +++ (3 +++ VNil))