Created
June 27, 2019 22:38
-
-
Save Eluss/31bd886cda4efea404d29e4dc242372a to your computer and use it in GitHub Desktop.
Revisions
-
Eluss created this gist
Jun 27, 2019 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,173 @@ struct Dog { var name: String } struct Person { var name: String var age: Int var dog: Dog } var dog = Dog(name: "Bark") var person = Person(name: "Foo", age: 12, dog: dog) struct Lens<Whole, Part> { let get: (Whole) -> Part let set: (Part) -> (Whole) -> Whole } extension Person { enum lens { static let dog: Lens<Person, Dog> = Lens( get: { person in return person.dog }, set: { newDog in return { person in var newPerson = person newPerson.dog = newDog return newPerson } }) static let age: Lens<Person, Int> = Lens( get: { person in return person.age}, set: { newAge in return { person in var newPerson = person newPerson.age = newAge return newPerson } }) static let name: Lens<Person, String> = Lens.init( get: { whole in return whole.name }, set: { newPart in { oldWhole in var whole = oldWhole whole.name = newPart return whole }}) } } extension Dog { enum lens { static let name: Lens<Dog, String> = Lens.init( get: { whole in return whole.name }, set: { newPart in { oldWhole in var whole = oldWhole whole.name = newPart return whole }}) } } //print(Person.lens.dog.get(person)) //let newDog = Dog(name: "Reksio") //let function: (Person) -> Person = Person.lens.dog.set(newDog) //print(function(person)) /// /// /// precedencegroup PipelineOperator { associativity: left } infix operator |> : PipelineOperator func |> (lhs: Person, rhs: (Person) -> Person) -> Person { return rhs(lhs) } let newPerson = person |> Person.lens.name.set("Astek") |> Person.lens.age.set(30) |> Person.lens.dog.set(Dog(name: "Kik")) //print(newPerson) /// precedencegroup SetOperator { associativity: none higherThan: PipelineOperator } infix operator .~ : SetOperator infix operator %~ : SetOperator extension Lens { static func .~ (lhs: Lens<Whole, Part>, rhs: Part) -> (Whole) -> Whole { return { whole in return lhs.set(rhs)(whole) } } static func %~ (lhs: Lens<Whole, Part>, rhs: @escaping (Part) -> Part) -> (Whole) -> Whole { return { whole in let part = lhs.get(whole) let newPart = rhs(part) let newWhole = lhs.set(newPart)(whole) return newWhole } } } let newPerson2 = person |> Person.lens.name .~ "Eliasz" |> Person.lens.age %~ { age in return age * 2} |> Person.lens.dog .~ Dog(name: "Olo") print(newPerson2) //Lens<A, B> + Lens<B, C> = Lens<A, C> precedencegroup ChainOperator { associativity: left higherThan: SetOperator } infix operator .. : ChainOperator //Whole // Part // Subpart extension Lens { static func .. <Subpart>(lhs: Lens<Whole, Part>, rhs: Lens<Part, Subpart>) -> Lens<Whole, Subpart> { return Lens<Whole, Subpart>.init( get: { whole in let part = lhs.get(whole) let subpart = rhs.get(part) return subpart }, set: { newSubpart in return { whole in let part = lhs.get(whole) let newPart = rhs.set(newSubpart)(part) let newWhole = lhs.set(newPart)(whole) return newWhole } }) } } let dogsName: Lens<Person, String> = Person.lens.dog..Dog.lens.name extension Person { enum deepLens { static let dogsName = Person.lens.dog..Dog.lens.name } } let newPerson3 = person |> Person.lens.name .~ "Test" |> Person.lens.age %~ { age in return age * 2} |> Person.deepLens.dogsName .~ "XX" print(newPerson3)