Last active
April 26, 2016 03:20
-
-
Save naoty/174e958f94f7eda562d38786cc3f1862 to your computer and use it in GitHub Desktop.
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 UIKit | |
struct Lens<A, B> { | |
private let getter: A -> B | |
private let setter: (A, B) -> A | |
init(getter: A -> B, setter: (A, B) -> A) { | |
self.getter = getter | |
self.setter = setter | |
} | |
} | |
extension Lens { | |
func get(from: A) -> B { | |
return getter(from) | |
} | |
func set(from: A, _ to: B) -> A { | |
return setter(from, to) | |
} | |
func modify(from: A, f: B -> B) -> A { | |
return set(from, f(get(from))) | |
} | |
} | |
extension Lens { | |
func compose<C>(other: Lens<B, C>) -> Lens<A, C> { | |
return Lens<A, C> ( | |
getter: { (a: A) -> C in | |
other.get(self.get(a)) | |
}, | |
setter: { (a: A, c: C) -> A in | |
self.set(a, other.set(self.get(a), c)) | |
} | |
) | |
} | |
} | |
infix operator >>> { associativity left } | |
func >>><A, B, C>(lens: Lens<A, B>, other: Lens<B, C>) -> Lens<A, C> { | |
return lens.compose(other) | |
} | |
let frameLens = Lens<UIView, CGRect>(getter: { $0.frame }, setter: { UIView(frame: $1) }) | |
let sizeLens = Lens<CGRect, CGSize>(getter: { $0.size }, setter: { CGRect(origin: $0.origin, size: $1) }) | |
let widthLens = Lens<CGSize, CGFloat>(getter: { $0.width }, setter: { CGSize(width: $1, height: $0.height) }) | |
let heightLens = Lens<CGSize, CGFloat>(getter: { $0.height }, setter: { CGSize(width: $0.width, height: $1) }) | |
let originLens = Lens<CGRect, CGPoint>(getter: { $0.origin }, setter: { CGRect(origin: $1, size: $0.size) }) | |
let xLens = Lens<CGPoint, CGFloat>(getter: { $0.x }, setter: { CGPoint(x: $1, y: $0.y) }) | |
let yLens = Lens<CGPoint, CGFloat>(getter: { $0.y }, setter: { CGPoint(x: $0.x, y: $1) }) | |
let view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 500)) | |
print(view) //=> <UIView: 0x7fb06bc18ba0; frame = (0 0; 300 500); layer = <CALayer: 0x7fb06bc06000>> | |
print((frameLens >>> sizeLens >>> widthLens).set(view, 100)) //=> <UIView: 0x7fb06bd22490; frame = (0 0; 100 500); layer = <CALayer: 0x7fb06bd21c30>> | |
print((frameLens >>> originLens >>> yLens).set(view, 50)) //=> <UIView: 0x7fb06bd26ff0; frame = (0 50; 300 500); layer = <CALayer: 0x7fb06bd24ee0>> | |
print((frameLens >>> sizeLens >>> heightLens).modify(view, f: { $0 * 2 })) //=> <UIView: 0x7fb06bf2b2d0; frame = (0 0; 300 1000); layer = <CALayer: 0x7fb06bf27ff0>> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment