kleisli on Nostr: trait Monad[F[_]] { def pure[A](value: A): F[A] def flatMap[A, B](fa: F[A])(f: A => ...
trait Monad[F[_]] {
def pure[A](value: A): F[A]
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
}
case class Reader[R, A](run: R => A)
given ReaderMonad[R]: Monad[[A] =>> Reader[R, A]] with {
def pure[A](value: A): Reader[R, A] = Reader(_ => value)
def flatMap[A, B](fa: Reader[R, A])(f: A => Reader[R, B]): Reader[R, B] = Reader(r => {
val a = fa.run(r)
f(a).run(r)
})
}
case class Config(username: String, password: String)
trait Service {
def doSomething(): String
}
class RealService(config: Config) extends Service {
def doSomething(): String = {
s"Doing something with ${config.username}"
}
}
type ConfigReader[A] = Reader[Config, A]
val config = Config("username", "password")
val service: RealService = createService.run(config)
println(service.doSomething())
def pure[A](value: A): F[A]
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
}
case class Reader[R, A](run: R => A)
given ReaderMonad[R]: Monad[[A] =>> Reader[R, A]] with {
def pure[A](value: A): Reader[R, A] = Reader(_ => value)
def flatMap[A, B](fa: Reader[R, A])(f: A => Reader[R, B]): Reader[R, B] = Reader(r => {
val a = fa.run(r)
f(a).run(r)
})
}
case class Config(username: String, password: String)
trait Service {
def doSomething(): String
}
class RealService(config: Config) extends Service {
def doSomething(): String = {
s"Doing something with ${config.username}"
}
}
type ConfigReader[A] = Reader[Config, A]
val config = Config("username", "password")
val service: RealService = createService.run(config)
println(service.doSomething())