Skip to content

Instantly share code, notes, and snippets.

@sidnt
Created December 15, 2020 04:39
Show Gist options
  • Save sidnt/646aa3cf5c34892a0f7cce4f7ccb8742 to your computer and use it in GitHub Desktop.
Save sidnt/646aa3cf5c34892a0f7cce4f7ccb8742 to your computer and use it in GitHub Desktop.
package lzio
import zio._
import console._
object helpers {
type ??? = Nothing
case class User(name: String, age: Int)
val u1 = User("Martin", 42)
type Year = Short
case class Country(name: String, capital: String, foundedIn: Year)
val c1 = Country("Switzerland", "Bern", 1848)
def makeMessage(i: Int): String = "the int> " + i
def makeMessage(u: User): String = s"hello ${u.name} | your age is ${u.age}"
def makeMessage(u: User, c:Country): String =
s"found user: ${u.name} | found country: ${c.name}"
}; import helpers._
object demo1 extends App {
/** wazp that depends on type R
* and returns it back as is
* . declare the types
* . provide the implementation
* . run it
*/
type R = Int
lazy val z1: ZIO[Int, Nothing, Int] = for {
e <- ZIO.environment[Int]
} yield e
val z1b: ZIO[Any, Nothing, Int] = z1.provide(88)
val printEnvironment = for {
i <- z1b
_ <- putStrLn("got in from the environment: " + i)
} yield ()
lazy val z1p: URIO[Console, ExitCode] = printEnvironment.exitCode
// def run(args: List[String]) = z1p
/** wazp that depends on type R
* and projects a value of type A
* from that type R
* using the given projection function
* . types, then
* . implementation
* . run
*/
type A = String
def projectionFunction(r:Int): String = s"projecting Int to String: " + r.toString()
lazy val z2: ZIO[Int, Nothing, String] =
for {
s <- ZIO.access[Int](i => projectionFunction(i))
} yield s
val z2p:ZIO[Any, Nothing, String] = z2.provide(77)
val z2b: ZIO[Console, Nothing, Unit] = for {
s <- z2p
_ <- putStrLn(s)
} yield ()
// lazy val z2p: UIO[ExitCode] = ???
def run(args: List[String]) = z2b.exitCode
}
object demo2 extends App {
/** wazp that depends on type User
* but does nothing with it, just exit simply
*/
lazy val z1: ZIO[User with Console, Nothing, ExitCode] =
for {
_ <- ZIO.access[User](identity)
ec <- putStrLn("bye bye").exitCode
} yield ec
// val z2 = z1.provide(u1)
// lazy val z1p: UIO[ExitCode] = z1.provideSome(u1)
// def run(args: List[String]) = z1p
/** wazp that depends on User type in R
* and creates a message out of it
* and prints it out to the console
*/
lazy val z2: ZIO[User, Nothing, String] =
for {
u <- ZIO.access[User](identity)
m = makeMessage(u)
} yield m
val z2b = z2.provide(u1)
val z2c: ZIO[Console, Nothing, Unit] = for {
m <- z2b
_ <- putStrLn(m)
} yield ()
val z2d:ZIO[Console, Nothing, ExitCode] = z2c.exitCode
// lazy val z2p: UIO[ExitCode] = ???
def run(args: List[String]) = z2d
}
object demo3 extends App {
/** wazp that depends on type User & Country
* generates the message from provided function
* prints it to the console
*/
lazy val z1: ZIO[User with Country, Nothing, String] =
for {
u <- ZIO.access[User](identity)
c <- ZIO.access[Country](identity)
m = makeMessage(u,c)
} yield m
val uwc: User with Country = ???
val z2 = z1.provide(uwc)
val z2b: ZIO[User with Country with Console, Nothing, Unit] =
for {
m <- z1
_ <- putStrLn(m)
} yield ()
val z3 = z2
val uwc2: User with Country with Console = ???
lazy val z1p: UIO[ExitCode] = ???
def run(args: List[String]) = z1p
}
object demo4 extends App {
/** create a Has[User]
*/
lazy val hu1: Has[User] = Has(u1)
/** extract a user from a Has[User]
*/
lazy val u1Fhu1: User = hu1.get
/** create a Has[Country]
*/
lazy val hc1: Has[Country] = Has(c1)
/** extract a country from a Has[Country]
*/
lazy val c1Fhc1: Country = hc1.get
/** wazp that depends on Has[User] with Has[Country]
* provide the appropriate environment
* make the message
* and then print it
*/
lazy val z1: ZIO[Has[User] with Has[Country], Nothing, String] =
for {
u <- ZIO.access[Has[User]](_.get)
c <- ZIO.access[Has[Country]](_.get)
m = makeMessage(u,c)
} yield m
val z1b = z1.provide(hu1 ++ hc1)
val z1c = for {
m <- z1b
_ <- putStrLn(m)
} yield ()
// lazy val z1p: UIO[ExitCode] = ???
def run(args: List[String]) = z1c.exitCode
}
object demo5 {
/** a country service injected into
* a user service
* to provide messages like above
* demonstrate the wiring
*/
object country {
type Country = Has[country.Service]
trait Service {
val name: String
val capital: String
val foundedIn: Year
}
val switzerland: ZLayer[Any, Nothing, Country] =
ZLayer.succeed(new country.Service {
val name: String = "Switzerland"
val capital: String = "Bern"
val foundedIn: helpers.Year = 1894
})
}
object user {
type User = Has[user.Service]
trait Service {
val name: String
val age: Int
}
val chet: ZLayer[Any, Nothing, User] =
ZLayer.succeed(new user.Service {
val name: String = "Chet"
val age: Int = 24
})
}
object message {
type Message = Has[message.Service]
trait Service {
val message: String
}
val m1: ZLayer[User with Country, Nothing, Message] =
ZLayer.fromFunction[user.User with country.Country, message.Service]( uwc => new message.Service {
val message: String = makeMessage(uwc.get[User], uwc.get[Country])
})
}
/** swapping layers
*
*/
/** very specialized type of layer
* usually a layer which is quite optional
* for testing
* we have a test layer / test harness layer
* we're using the same api as live layers
* as all have got the same interface
* but the test implementation is different from live implementation
* .
* logging
* we might want to have logs of everything, eg
* user events / network events / events->proposals->action
* action being accepted by the
* ....
* aspect takes a network layer
* returns a network layer with logging
* the incoming/outcoming api is the same
* but it has done
* it has modified teh network layer
* to add logging to it
* .
* they are special layer
* where it takes an existing layer
* and it modifies it
*
*/
val _ = null
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment