The “finally tagless” style for organising software functionalities is more and more popular. Grafter supports this approach by allowing you to specify a type constructor as the type parameter of a component:
import org.zalando.grafter.macros.{defaultReader, reader}
import cats.Monad
@defaultReader[DatabaseUserOperations]
trait UserOperations[F[_]] {
def getUser(name: String): F[User]
def createUser(name: String): F[User]
}
@reader
case class DatabaseUserOperations[F[_]](config: DbConfig)(implicit val m: Monad[F]) extends UserOperations[F] {
def getUser(name: String): F[User] = ???
def createUser(name: String): F[User] = ???
}
As you can see there is a minor drawback because you would probably like to write case class DatabaseUserOperations[F[_] : Monad]
. This is not currently possible because of this Scala bug. Please vote for it or even better propose a PR on the Scala project!