Scala: Generics for return type Seq [A] or Future [Seq [A]]

Problem

I have two classes that look like this:

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

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

The only difference between the two classes is that Now returns Seq, and later returns Future Seq. I would like these two classes to have the same interface

What i tried

This seemed to be ideal for higher types, given how Seq and Future [Seq] should have only one type parameter.

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

Am I using higher type types incorrectly? Am I delivering the future [Seq] wrong? Is there a way to allow Now and Later to use the same interface?

+3
source share
3 answers

You need a composition type:

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

Or if you just need it in this place

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

. scalaz ( , , , -, .)

+4

, :

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

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

Here Need is the Scalaza monad, which basically acts as a lazy identity with the object that it contains. There are other alternatives in the same vein, but the fact is that the only thing you need to know about Futureand Needis that they are monads. You treat them the same way, and you decide to use one or the other in another place.

+1
source

All Articles