Scala:返回类型Seq [A]或未来[Seq [A]]的泛型

时间:2014-01-13 22:36:48

标签: scala generics higher-kinded-types

问题

我有两个类如下:

class Now {
  def do[A](f: Int => A): Seq[A]
}

class Later {
  def do[A](f: Int => A): Future[Seq[A]]
}

两个类之间的唯一区别是,Now返回Seq,而Later返回Future Seq。我希望这两个类共享相同的接口

我尝试过什么

考虑到Seq和Future [Seq]如何只需要一个类型参数,这似乎非常适合高等级的类型。

trait Do[F[_]] {
  def do[A](f: Int => A): F[A]
}

// Compiles
class Now extends Do[Seq] {
  def do[A](f: Int => A): Seq[A]
}

// Does not compile. "type Seq takes type parameters" and
// "scala.concurrent.Future[<error>] takes no type parameters, expected: one"
class Later extends Do[Future[Seq]] {
  def do[A](f: Int => A): Future[Seq[A]]
}

我是否错误地使用了更高级别的类型?我错误地提供了Future [Seq]吗?有没有办法让Now和Later共享同一个界面?

3 个答案:

答案 0 :(得分:4)

您需要类型组合:

trait Composition[F[_], G[_]] { type T[A] = F[G[A]] }

class Later extends Do[Composition[Future, Seq]#T] {
  def do[A](f: Int => A): Future[Seq[A]]
}

或者如果您只需要在这一个地方

class Later extends Do[({ type T[A] = Future[Seq[A]] })#T] {
  def do[A](f: Int => A): Future[Seq[A]]
}

请参阅scalaz(我可以宣誓它包括一般类型的构图,但显然不是。)

答案 1 :(得分:1)

相信你想要这个:

import scala.language.higherKinds
import scala.concurrent.Future

object Main {
  type Id[A] = A

  trait Do[F[_]] {
    // Notice the return type now contains `Seq`.
    def `do`[A](f: Int => A): F[Seq[A]]
  }

  class Now extends Do[Id] {
    override def `do`[A](f: Int => A): Seq[A] = ???
  }

  class Later extends Do[Future] {
    override def `do`[A](f: Int => A): Future[Seq[A]] = ???
  }
}

但是如果你想要更通用的东西,抽象方法在其返回类型中是完全通用的,那么@AlexeyRomanov的类型组合答案就是你要找的那个。

答案 2 :(得分:1)

Alexey的解决方案非常聪明,可以回答你提出的问题。但是,我认为你提出了这个问题。

您从这两个界面开始:

class Now {
  def do[A](f: Int => A): Seq[A]
}

class Later {
  def do[A](f: Int => A): Future[Seq[A]]
}

并希望修改Later,以便实现此目的:

trait Do[F[_]] {
  def do[A](f: Int => A): F[A]
}

然而,你在这里失去了一个机会来抽象现在或以后的事情。您应该将Do更改为:

trait Do[F[_]] {
  def do[A](f: Int => A): F[Seq[A]]
}

并将Now更改为:

class Now {
  def do[A](f: Int => A): Need[Seq[A]]
}

这里,Need是一个Scalaz monad,它基本上就像它所包含的对象的惰性身份。同样有其他选择,但关键是你需要知道的关于FutureNeed的唯一事情是它们是monad。你对待它们是一样的,你决定在其他地方使用其中一个。