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.