This is a basic Scala Tagless Final pattern implementation of a contrived login process. It doesn't compile because as it shows near the end 'No implicits found for parameters ...'
But if I remove ': Monad: LoginProcessAlgebra[F]'
from the program generic type that specific error goes away but the for-comprehension starts to complain because F[_]
is no longer narrowed down to a Monad
Question: Why does Scala think State isn't a Monad?
import cats.Monad
import cats.data.State
import cats.implicits._
import java.util.UUID
import scala.language.higherKinds
case class Credentials(uid: String, pwd: String)
case class Session(sessionId: String, credentials: Credentials)
object LoginProcessTaglessFinal {
trait LoginProcessAlgebra[F[_]] {
def captureCredentials(name: String, password: String): F[Credentials]
def login(credentials: Credentials): F[Session]
}
type LoginProcessState = State[LoginProcessAlgebra[_], _]
type LoginProcessStateA[A] = LoginProcessState[A]
implicit object LoginProcessInterpreterUsingState extends LoginProcessAlgebra[LoginProcessStateA] {
override def captureCredentials(name: String, password: String): LoginProcessStateA[Credentials] =
State(login => (login, Credentials(name, password)))
override def login(credentials: Credentials): LoginProcessStateA[Session] =
State(login => (login, Session(UUID.randomUUID().toString, credentials)))
}
def program[F[_]: Monad: LoginProcessAlgebra[F]](userName: String, password: String)
(implicit interpreter: LoginProcessAlgebra[F]): F[Session] = for {
credentials <- interpreter.captureCredentials(userName, password)
session <- interpreter.login(credentials)
} yield session
val sessionState = program("someUserName", "p455w0rd")
//compile error here
//due to 'No implicits found for parameters ...'
}