I am trying to use the first time tagless final pattern in Scala and struggling a bit.
I have the following algebras definition:
trait DbSetting[F[_]] {
def read(url: String, user: String, pw: String): F[DbParameter]
}
trait Environment[F[_]] {
def get(v: String) : F[Option[String]]
}
and the interpreters implementation:
final case class DbParameter(url: String, user: String, pw: String)
sealed trait DbError extends NoStackTrace
case object DbSettingError extends DbError
sealed trait DbError extends NoStackTrace
case object DbSettingError extends DbError
// Environment implementation
object Environment {
def apply[F[_]](implicit ev: Environment[F]): ev.type = ev
def impl[F[_]: Sync]: Environment[F] = new Environment[F] {
override def get(v: String): F[Option[String]] =
Sync[F].delay(sys.env.get(v))
}
}
// DbSetting implementation
class DbSystemEnvironment[F[_] : MonadError[*, Throwable]] private(env: Environment[F])
extends DbSetting[F] {
override def read(url: String, user: String, pw: String): F[DbParameter] = env.get(url)
}
What I am trying to do is, to compose Environment
into DbSystemEnvironment
. The problem here is, I can not get the value out of env.get(url)
because, I do not know anything about F
in DbSystemEnvironment
, except it is a MonadError
.
How to get the value out of env.get(url)::F[Option[String]]
?
In addition, if env.get(url)
returns Nothing
in read
function, then it should return MonadError
.
If I understand your question correctly you are asking how to extract the returned value from calling env.get(url)
and then map it to a F[DbParameter]
.
Since you have MonadError
for your F[_]
you should be able to map the result pretty readily by doing something like this:
import cats.syntax.flatMap._
import cats.syntax.applicative._
import cats.syntax.applicativeError._
override def read(url: String, user: String, pw: String): F[DbParameter] =
env.get(url).flatMap {
case Some(ev) => DbParameter(ev, user, pw).pure[F]
case None => (new Exception("No environment parameter found!")).raiseError[F, DbParameter]
}