taking it further, you can do:```
inline fun <TARGET : Any, reified T> BiDiLensSpec<TARGET, String>.compositeLensSpec(crossinline fn: BiDiLensSpec<TARGET, String>.(TARGET) -> T) = LensSpec<TARGET, T>(
T::class.java.name, ObjectParam, LensGet { _, target -> listOf(fn(target)) }).required(T::class.java.name)
inline fun <TARGET : Any, reified OUT, A, B> BiDiLensSpec<TARGET, String>.composite(
crossinline fn: (A, B) -> OUT, a: Lens<TARGET, A>, b: Lens<TARGET, B>) = compositeLensSpec { fn(a(it), b(it)) }
inline fun <TARGET : Any, reified OUT, A, B> BiDiLensSpec<TARGET, String>.composite2(
crossinline fn: (A, B) -> OUT, crossinline a: BiDiLensSpec<TARGET, String>.() -> Lens<TARGET, A>, crossinline b: BiDiLensSpec<TARGET, String>.() -> Lens<TARGET, B>) = compositeLensSpec { fn(a()(it), b()(it)) }
data class MyThing(val a: Int, val b: String)
fun main() {
val lens = EnvironmentKey.composite(::MyThing,
EnvironmentKey.int().required("FOO"), EnvironmentKey.required("VAR"))
val lens2 = EnvironmentKey.composite2(::MyThing, { int().required("FOO") }, { required("VAR") })
lens(Environment.ENV)
lens2(Environment.ENV)
}
```