Skip to content

Instantly share code, notes, and snippets.

@etorreborre
Last active March 10, 2016 16:49
Show Gist options
  • Save etorreborre/2f80c4ca275562926767 to your computer and use it in GitHub Desktop.
Save etorreborre/2f80c4ca275562926767 to your computer and use it in GitHub Desktop.
Use of lenses to access only specific parts of a configuration when using the Reader monad
package application
import cats.data.Reader
import cats.data.Kleisli._
import monocle.macros.Lenses
object Application {
/**
* A general configuration for the system
*/
@Lenses
case class SystemConfiguration(host: String, port: Int)
/**
* A configuration for the billing interactions / module
*/
@Lenses
case class BillingRequestConfiguration(user: String, billingUrl: String, system: SystemConfiguration)
/**
* A configuration for the product interactions / module
*/
@Lenses
case class ProductRequestConfiguration(user: String, productUrl: String, system: SystemConfiguration)
/**
* A configuration for the full system, including all modules
*/
@Lenses
case class FullConfiguration(billing: BillingRequestConfiguration, product: ProductRequestConfiguration)
// functions using the Billing configuration
object BillingRequest {
type BillingId = String
import BillingRequestConfiguration._
import SystemConfiguration._
// this function doesn't need to know about the product configuration
def createBilling: Reader[BillingRequestConfiguration, BillingId] =
Reader { conf =>
// the billing configuration data is accessible
// this can contains some request-scoped data
println("accessing the billing system to create a billing id. Url is: "+conf.billingUrl+
// more general configuration data is also accessible
" main host is "+conf.system.host)
// create a billing id
"12345"
}
}
// functions using the Product configuration
object ProductRequest {
type ProductId = String
import ProductRequestConfiguration._
import SystemConfiguration._
def createProduct: Reader[ProductRequestConfiguration, ProductId] =
Reader { conf =>
println("accessing the product system to create a product id. Url is: "+conf.productUrl+
" main host is "+conf.system.host)
// create a product id
"67890"
}
}
// functions using both Billing and Product configurations
object SystemRequest {
import BillingRequest._
import ProductRequest._
import FullConfiguration._
def createBillingAndProduct: Reader[FullConfiguration, (BillingId, ProductId)] =
for {
// get the full configuration
conf <- ask
// use only the billing configuration for the billing operations
billingId <- createBilling.local(billing.get)
// use only the product configuration for the product operations
productId <- createProduct.local(product.get)
} yield (billingId, productId)
}
}
@etorreborre
Copy link
Author

Not different, it was just me playing with the API for accessors. conf.system.host is way better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment