Home > OS >  Difference in Scala between abstracting class versus method
Difference in Scala between abstracting class versus method

Time:10-03

What's the difference in Scala between abstracting the class versus abstracting the method? When use one vs the other ?

class lookup[F[_]] {
  def searchUser(username: Username, email: Email): F[Option[User]]
}

object lookup {
  def searchUser[F[_]](username: Username, email: Email): F[Option[User]]
}

CodePudding user response:

Semantics is different for these two cases.

In the first case F is resolved upon creating an instance of the class

class lookup[F[_]] {
  def searchUser(username: Username, email: Email): F[Option[User]] = ???
}

val l1 = new lookup[Future]
val l2 = new lookup[List]
l1.searchUser(username1, email1): Future[Option[User]]
l2.searchUser(username2, email2): List[Option[User]]

In the second case F is resolved upon method call

object lookup {
  def searchUser[F[_]](username: Username, email: Email): F[Option[User]] = ???
}

lookup.searchUser[Future](username1, email1): Future[Option[User]]
lookup.searchUser[List](username2, email2): List[Option[User]]

Suppose you will add one more method

class lookup[F[_]] {
  def searchUser(username: Username, email: Email): F[Option[User]] = ???
  def deleteUser(user: User): F[Unit] = ???
}

Here you know that F is the same for both methods. But for

object lookup {
  def searchUser[F[_]](username: Username, email: Email): F[Option[User]] = ???
  def deleteUser[F[_]](user: User): F[Unit] = ???
}

F in one method and F in another method can be different.

Also lookup[F[_]] can be used in implicits / type classes / context bounds (this is useful in tagless final approach)

def foo[F[_]: lookup] = ???
def foo[F[_]](implicit l: lookup[F]) = ???

while in the second case you lose this ability.

  • Related