Skip to content

Instantly share code, notes, and snippets.

@iamanandkris
Last active December 23, 2021 06:27
Show Gist options
  • Save iamanandkris/0078da0d619fc7cef9dd9a9c1c883298 to your computer and use it in GitHub Desktop.
Save iamanandkris/0078da0d619fc7cef9dd9a9c1c883298 to your computer and use it in GitHub Desktop.
Attempt to use State monad within ZIO
import cats.data.State
import scalaz.zio.{DefaultRuntime, Task, ZIO}
type UserID = String
case class UserProfile(name:String)
trait Database[F[_]] {
def lookup(id: UserID): Task[F[UserProfile]]
def update(id: UserID, profile: UserProfile): Task[F[Unit]]
}
trait Logger[F[_]] {
def info(id: String): Task[F[Unit]]
}
trait Operation
trait DatabaseOperation extends Operation
case class UserUpdated(id:UserID, profile:UserProfile) extends DatabaseOperation
case class UserLookedUp(id:UserID) extends DatabaseOperation
trait LoggerOperation extends Operation
case class MessageLogged(message:String) extends LoggerOperation
type TestState[A] = cats.data.State[List[Operation], A]
trait TestDatabaseService extends Database[TestState] {
private var map: Map[UserID, UserProfile] = Map("abc" -> UserProfile("testName"))
def lookup(id: UserID): Task[TestState[UserProfile]] =
Task(for{
_ <- State.modify[List[Operation]](s => UserLookedUp(id) :: s)
s <- State.inspect[List[Operation], UserProfile](s => map(id))
}yield s)
def update(id: UserID, profile: UserProfile): Task[TestState[Unit]] =
Task.effect {for{
_ <- State.modify[List[Operation]](s => UserUpdated(id, profile) :: s)
s <- State.inspect[List[Operation], Unit](s => map = map + (id -> profile) )
}yield s}
}
trait TestLoggerService extends Logger[TestState] {
def info(id: String): Task[TestState[Unit]] =
Task(for{
s <- State.modify[List[Operation]](s => MessageLogged(id) :: s)
_ <- State.inspect[List[Operation], Unit](s => ())
}yield s)
}
object FinalEnv extends TestLoggerService with TestDatabaseService
val lookedupProfile: ZIO[Database[TestState] with Logger[TestState], Throwable, TestState[UserProfile]] =
for {
profile <- ZIO.accessM[Database[TestState]](x => x.lookup("abc"))
x <- ZIO.access[Logger[TestState]](x => profile.map(xs => x.info(xs.name)))
} yield profile
val runtime = new DefaultRuntime {}
runtime.unsafeRun(lookedupProfile.provide(FinalEnv)).run(Nil).value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment