Scala:返回类型 seq[a] 或 future[a]] 的泛型



问题

我有两个类,如下所示:

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

这两个类之间的唯一区别是 Now 返回一个 Seq,稍后返回一个 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]]
}

我是否错误地使用了更高种类的类型?我是否错误地供应了未来[序列]?有没有办法允许现在和以后共享同一个界面?

你需要类型组合:

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(我可以发誓它包括一般类型的组合,但显然不是。

我相信你想要这个:

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的类型组合答案就是你要找的答案。

阿列克谢的解决方案非常聪明,回答了你提出的问题。但是,我认为您提出了问题。

您从以下两个接口开始:

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,您唯一需要了解的是它们是单子。你对它们一视同仁,然后决定在其他地方使用其中一个。

最新更新