Last active
October 23, 2023 20:30
-
-
Save elm4ward/1d15949cfb792a6819b777b2d1ee329a to your computer and use it in GitHub Desktop.
Something Bijection
This file contains 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
// -------------------------------------------------------------------------------- | |
// MARK: - Prerequsites | |
// -------------------------------------------------------------------------------- | |
/// Compose Operator | |
precedencegroup BijectionGroup { associativity: left } | |
infix operator <> : BijectionGroup | |
/// Typealias for a binary function | |
typealias Bin<T> = (T) -> (T) -> T | |
/// Curry - 2nd arg - then 1st arg | |
func curry<A, B, C>(_ f: @escaping (A, B) -> C) -> (B) -> (A) -> C { | |
return { b in { a in f(a, b) } } | |
} | |
// -------------------------------------------------------------------------------- | |
// MARK: - Bijection | |
// -------------------------------------------------------------------------------- | |
struct Bijection<A, B> { | |
let forward: (A) -> B | |
let backward: (B) -> A | |
init(_ f: @escaping (A) -> B, _ b: @escaping (B) -> A) { | |
forward = f | |
backward = b | |
} | |
func compose<C>(_ t: Bijection<B, C>) -> Bijection<A, C> { | |
let f: (A) -> C = { (a: A) in t.forward(self.forward(a)) } | |
let b: (C) -> A = { (c: C) in self.backward(t.backward(c)) } | |
return Bijection<A, C>(f, b) | |
} | |
} | |
func <> <A, B, C>(_ lhs: Bijection<A, B>, _ rhs: Bijection<B, C>) -> Bijection<A, C> { | |
return lhs.compose(rhs) | |
} | |
// -------------------------------------------------------------------------------- | |
// MARK: - In Action | |
// -------------------------------------------------------------------------------- | |
let add: Bin<Double> = curry(+) | |
let sub: Bin<Double> = curry(-) | |
let mul: Bin<Double> = curry(*) | |
let div: Bin<Double> = curry(/) | |
let move: (Double) -> Bijection<Double, Double> = { Bijection(add($0), sub($0)) } | |
let scale: (Double) -> Bijection<Double, Double> = { Bijection(mul($0), div($0)) } | |
/// This is the composed bijection | |
let b = move(10) <> scale(5) <> move(1) <> scale(-2) <> move(100) <> scale(10) | |
let result1 = b.forward(2) | |
let result2 = b.backward(b.forward(2)) | |
let result3 = b.forward(b.backward(b.forward(2))) | |
print(result1 == result3) | |
print(result2 == 2) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment