Last active
March 10, 2016 16:49
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
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
How is
(system ^|-> host).get(conf)
different fromconf.system.host
?