Created
February 6, 2018 08:15
-
-
Save nomisRev/8017570f2adbb744e9eaed5d21b0131a to your computer and use it in GitHub Desktop.
Added traversal
This file contains hidden or 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
import arrow.core.Option | |
import arrow.core.identity | |
import arrow.data.ListKW | |
import arrow.data.ListKWHK | |
import arrow.data.ListKWKind | |
import arrow.data.ev | |
import arrow.data.k | |
import arrow.lenses | |
interface BoundSetter<S, A> { | |
fun modify(f: (A) -> A): S | |
} | |
fun <T, S, A> BoundSetter<T, S>.setter(setter: Setter<S, A>): BoundSetter<T, A> { | |
return object : BoundSetter<T, A> { | |
override fun modify(f: (A) -> A): T = [email protected] { setter.modify(it, f) } | |
} | |
} | |
fun <T> T.setter() = object : BoundSetter<T, T> { | |
override fun modify(f: (T) -> T) = f(this@setter) | |
} | |
fun <S, A> BoundSetter<S, A>.set(a: A) = modify { a } | |
//primitives | |
val <T, A> BoundSetter<T, A?>.nullable get() = setter(nullableOptional<A>().asSetter()) | |
val <T, A> BoundSetter<T, Option<A>>.some get() = setter(somePrism<A>().asSetter()) | |
val <T, A> BoundSetter<T, ListKW<A>>.each: BoundSetter<T, A> | |
get() =setter(listKWKindToListKW<A>().reverse() compose Traversal.fromTraversable<ListKWHK, A, A>().asSetter()) | |
//usage | |
@lenses | |
data class Street(val number: Int, val name: String) | |
@lenses | |
data class Address(val city: String, val street: Street) | |
@lenses | |
data class Company(val name: String, val address: Address) | |
@lenses | |
data class Employee(val name: String, val company: Company?) | |
@lenses | |
data class CompanyEmployees(val employees: ListKW<Employee>) | |
//Generated | |
val <T> BoundSetter<T, Employee>.name @JvmName("employeeName") get() = setter(employeeName().asSetter()) | |
val <T> BoundSetter<T, Employee>.company get() = setter(employeeCompany().asSetter()) | |
val <T> BoundSetter<T, Company>.name @JvmName("companyName") get() = setter(companyName().asSetter()) | |
val <T> BoundSetter<T, Company>.address get() = setter(companyAddress().asSetter()) | |
val <T> BoundSetter<T, Address>.city get() = setter(addressCity().asSetter()) | |
val <T> BoundSetter<T, Address>.street get() = setter(addressStreet().asSetter()) | |
val <T> BoundSetter<T, Street>.number get() = setter(streetNumber().asSetter()) | |
val <T> BoundSetter<T, Street>.name get() = setter(streetName().asSetter()) | |
val <T> BoundSetter<T, CompanyEmployees>.employees get() = setter(companyEmployeesEmployees().asSetter()) | |
val john = Employee("John Doe", Company("Kategory", Address("Functional city", Street(42, "lambda street")))) | |
val jane = Employee("Jane Doe", Company("Kategory", Address("Functional city", Street(42, "lambda street")))) | |
val employees = CompanyEmployees(listOf(john, jane).k()) | |
fun main(args: Array<String>) { | |
john.setter().company.nullable.address.street.name.modify(String::capitalize).let(::println) | |
employees.setter().employees.each.company.nullable.address.street.name.modify(String::toUpperCase).let(::println) | |
} | |
//Missing from std | |
/** | |
* [Iso] that defines equality between [ListKWKind] and [LisKW] | |
*/ | |
fun <A> listKWKindToListKW(): Iso<ListKWKind<A>, ListKW<A>> = Iso( | |
get = { it.ev() }, | |
reverseGet = ::identity | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment