Reader Monad via ZIO

Usage

trait HasEnv {
  def env: Map[String, String]
}

def readEnv(name: String): zio.ZIO[HasEnv, Throwable, String] =
  zio.ZIO.environmentWithZIO { r =>
    zio.ZIO.attempt {
      r.get.env(name)
    }
  }
trait HasReadLn {
  def readLn(): String
}

def readLn: zio.ZIO[HasReadLn, Throwable, String] =
  zio.ZIO.environmentWithZIO { r =>
    zio.ZIO.attempt {
      r.get.readLn()
    }
  }
trait HasWrite {
  def write(output: String): Unit
}

def write(output: String): zio.ZIO[HasWrite, Throwable, Unit] =
  zio.ZIO.environmentWithZIO { r =>
    zio.ZIO.attempt {
      r.get.write(output)
    }
  }
def enProgram: zio.ZIO[HasReadLn with HasWrite, Throwable, Unit] =
  for {
    _    <- write("What's your name? ")
    name <- readLn
    _    <- write(s"Hello, ${name}!\n")
  } yield ()

def esProgram: zio.ZIO[HasReadLn with HasWrite, Throwable, Unit] =
  for {
    _    <- write("¿Cómo te llamas? ")
    name <- readLn
    _    <- write(s"¡Hola, ${name}!\n")
  } yield ()

def program: zio.ZIO[HasEnv with HasReadLn with HasWrite, Throwable, Unit] =
  for {
    lang <- readEnv("LANG")
    _    <- if (lang.startsWith("es")) {
              esProgram
            } else {
              enProgram
            }
  } yield ()
zio.Unsafe.unsafely {
//zio.Unsafe.unsafe { implicit u: zio.Unsafe =>
  zio.Runtime.default.unsafe.run(
    program.provide(
      zio.ZLayer.succeed(
        new HasEnv {
          override def env: Map[String, String] = sys.env
        }
      ),
      zio.ZLayer.succeed(
        new HasReadLn {
          override def readLn(): String = scala.io.StdIn.readLine()
        }
      ),
      zio.ZLayer.succeed(
        new HasWrite {
          override def write(output: String): Unit = print(output)
        }
      )
    )
  ).getOrThrowFiberFailure()
}

Demo

This file is literate Scala, and can be run using Codedown:

$ LANG=es_MX.UTF-8 scala-cli --scala 3.2.2 --dependency dev.zio::zio:2.0.6 \
  <(curl https://earldouglas.com/posts/effect-systems/zio.md | codedown scala)
¿Cómo te llamas? James
¡Hola, James!