Skip to content

Instantly share code, notes, and snippets.

@raymanoz
Created September 9, 2012 16:14
Show Gist options
  • Save raymanoz/3685345 to your computer and use it in GitHub Desktop.
Save raymanoz/3685345 to your computer and use it in GitHub Desktop.
Lense using TotallyLazy
import com.googlecode.totallylazy.Function1;
import com.googlecode.totallylazy.Function2;
public class Lenses {
public static void main(String[] args) throws Exception {
Person rhys = new Person("rhys", 33, new Address("2 east lane", new Postcode("se16", "4uq")));
Person older_rhys = Person.lenses.age.set(34, rhys);
System.out.println(older_rhys);
Person rhys_at_e1 = Person.lenses.postcode.set(new Postcode("e1", "1aa"), rhys);
System.out.println(rhys_at_e1);
}
}
class Person {
final String name;
final int age;
final Address address;
Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
public String toString() {
return name + ": age=" + age + ", address=" + address;
}
public static class lenses {
public static final Lense<Person, Integer> age = Lense.lense(functions.age, functions.setAge);
public static final Lense<Person, Address> address = Lense.lense(functions.address, functions.setAddress);
public static final Lense<Person, Postcode> postcode = address.then(Address.lenses.postcode);
}
public static class functions {
public static final Function1<Person, Integer> age = new Function1<Person, Integer>() {
public Integer call(Person person) throws Exception {
return person.age;
}
};
public static final Function2<Integer, Person, Person> setAge = new Function2<Integer, Person, Person>() {
public Person call(Integer newAge, Person person) throws Exception {
return new Person(person.name, newAge, person.address);
}
};
public static final Function1<Person, Address> address = new Function1<Person, Address>() {
public Address call(Person person) throws Exception {
return person.address;
}
};
public static final Function2<Address, Person, Person> setAddress = new Function2<Address, Person, Person>() {
public Person call(Address newAddress, Person person) throws Exception {
return new Person(person.name, person.age, newAddress);
}
};
}
}
class Address {
final String street;
final Postcode postcode;
Address(String street, Postcode postcode) {
this.street = street;
this.postcode = postcode;
}
public String toString() {
return street + " " + postcode;
}
public static class lenses {
public static final Lense<Address, Postcode> postcode = Lense.lense(functions.postcode, functions.setPostcode);
}
public static class functions {
public static final Function1<Address, Postcode> postcode = new Function1<Address, Postcode>() {
public Postcode call(Address address) throws Exception {
return address.postcode;
}
};
public static final Function2<Postcode, Address, Address> setPostcode = new Function2<Postcode, Address, Address>() {
public Address call(Postcode newPostcode, Address address) throws Exception {
return new Address(address.street, newPostcode);
}
};
}
}
class Postcode {
final String outward;
final String inward;
Postcode(String outward, String inward) {
this.outward = outward;
this.inward = inward;
}
public String toString() {
return outward + " " + inward;
}
}
class Lense<A, B> {
private final Function1<A, B> get;
private final Function2<B, A, A> set;
private Lense(Function1<A, B> get, Function2<B, A, A> set) {
this.get = get;
this.set = set;
}
public static <A, B> Lense<A, B> lense(Function1<A, B> get, Function2<B, A, A> set) {
return new Lense<A, B>(get, set);
}
public A set(B b, A a) {
return set.apply(b,a);
}
public <C> Lense<A, C> then(final Lense<B, C> other) {
return lense(
get.then(other.get),
new Function2<C,A,A>() {
public A call(final C c, final A a) throws Exception {
return set(other.set(c, get.apply(a)), a);
}
}
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment