1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
|
// RUN: %target-run-simple-swift | %FileCheck %s
// REQUIRES: executable_test
func curry<T, U, V>(_ f: @escaping (T, U) -> V) -> (T) -> (U) -> V {
return { x in { y in f(x, y) } }
}
func curry<T1, T2, T3, T4>(_ f: @escaping (T1, T2, T3) -> T4) -> (T1) -> (T2) -> (T3) -> T4 {
return { x in { y in { z in f(x, y, z) } } }
}
func concat(_ x: String, _ y: String, _ z: String) -> String {
return x + y + z
}
@inline(never)
public func test_concat_closure(_ x: Int) -> String {
var x = x
let insult = curry(concat)("one ")(" two ")
var gs = insult(" three ")
if (x > 0) {
gs = gs + insult(" four ")
gs = gs + insult(" five ")
} else {
gs = gs + insult(" six ")
gs = gs + insult(" seven ")
}
if (x > 10) {
x += 100
}
return gs
}
public protocol P {
func val() -> Int32
}
struct CP: P {
let v: Int32
func val() -> Int32 {
return v
}
init(_ v: Int32) {
self.v = v
}
}
func compose(_ x: P, _ y: P, _ z: P) -> Int32 {
return x.val() + y.val() + z.val()
}
@inline(never)
public func test_compose_closure(_ x: Int) -> Int32 {
var x = x
let insult = curry(compose)(CP(1))(CP(2))
var gs = insult(CP(3))
if (x > 0) {
gs = gs + insult(CP(4))
gs = gs + insult(CP(5))
} else {
gs = gs + insult(CP(6))
gs = gs + insult(CP(7))
}
if (x > 10) {
x += 100
}
return gs
}
let insult = curry(+)("I'm with stupid ☞ ")
print(insult("😡")) // CHECK: I'm with stupid ☞ 😡
let plus1 = curry({ $0 + $1 })(1)
print(plus1(5)) // CHECK-NEXT: 6
let plus5 = curry({ $0 + $1 })(5)
print(plus5(5)) // CHECK-NEXT: 10
print(insult("😰")) // CHECK-NEXT: I'm with stupid ☞ 😰
let concat_one_two = curry(concat)("one ")(" two ")
print(concat_one_two(" three ")) // CHECK-NEXT: one two three
print(test_concat_closure(20)) // CHECK-NEXT: one two three one two four one two five
print(test_compose_closure(20)) // CHECK-NEXT: 21
// rdar://problem/18988428
func clamp<T: Comparable>(_ minValue: T, _ maxValue: T) -> (T) -> T {
return { n in max(minValue, min(n, maxValue)) }
}
let clampFoo2 = clamp(10.0, 30.0)
print(clampFoo2(3.0)) // CHECK-NEXT: 10.0
// rdar://problem/19195470
func pair<T,U> (_ a: T) -> (U) -> (T,U) {
return { b in (a,b) }
}
func pair_<T,U> (_ a: T) -> (_ b: U) -> (T,U) {
return { b in (a,b) }
}
infix operator <+>
func <+><T,U,V> (lhs: T?, rhs: @escaping (T) -> (U) -> V) -> (U) -> V? {
if let x = lhs {
return { y in .some(rhs(x)(y)) }
} else {
return { _ in nil }
}
}
let a : Int? = 23
let b : Int? = 42
print((b <+> pair)(a!) as Any) // CHECK-NEXT: (42, 23)
print((b <+> pair_)(a!) as Any) // CHECK-NEXT: (42, 23)
//
// rdar://problem/20475584
//
struct Identity<A> { let value: A }
struct Const<A, B> { let value: A }
func fmap<A, B>(_ f: @escaping (A) -> B) -> (Identity<A>) -> Identity<B> {
return { identity in Identity(value: f(identity.value)) }
}
func fmap<A, B>(_ f: @escaping (A) -> B) -> (Const<A, B>) -> Const<A, B> {
return { const in const }
}
// really Const()
func _Const<A, B>(_ a: A) -> Const<A, B> {
return Const(value: a)
}
func const<A, B>(_ a: A) -> (B) -> A {
return { _ in a }
}
// really Identity()
func _Identity<A>(_ a: A) -> Identity<A> {
return Identity(value: a)
}
func getConst<A, B>(_ c: Const<A, B>) -> A {
return c.value
}
func runIdentity<A>(_ i: Identity<A>) -> A {
return i.value
}
func view<S, A>(_ lens: @escaping (@escaping (A) -> Const<A, S>) -> (S) -> (@escaping (@escaping (A) -> S) -> (Const<A, S>) -> Const<A, S>) -> Const<A, S>) -> (S) -> A {
return { s in getConst(lens(_Const)(s)(fmap)) }
}
func over<S, A>(_ lens: @escaping (@escaping (A) -> Identity<A>) -> (S) -> (@escaping (@escaping (A) -> S) -> (Identity<A>) -> Identity<S>) -> Identity<S>) -> (@escaping (A) -> A) -> (S) -> S {
return { f in { s in runIdentity(lens({ _Identity(f($0)) })(s)(fmap)) } }
}
func set<S, A>(_ lens: @escaping (@escaping (A) -> Identity<A>) -> (S) -> (@escaping (@escaping (A) -> S) -> (Identity<A>) -> Identity<S>) -> Identity<S>) -> (A) -> (S) -> S {
return { x in { y in over(lens)(const(x))(y) } }
}
func _1<A, B, C, D>(_ f: @escaping (A) -> C) -> ((A, B)) -> (@escaping (@escaping (A) -> (A, B)) -> (C) -> D) -> D {
return { pair in { fmap in fmap({ ($0, pair.1) })(f(pair.0)) } }
}
func _2<A, B, C, D>(_ f: @escaping (B) -> C) -> ((A, B)) -> (@escaping (@escaping (B) -> (A, B)) -> (C) -> D) -> D {
return { pair in { fmap in fmap({ (pair.0, $0) })(f(pair.1)) } }
}
public func >>> <T, U, V> (f: @escaping (T) -> U, g: @escaping (U) -> V) -> (T) -> V {
return { g(f($0)) }
}
public func <<< <T, U, V> (f: @escaping (U) -> V, g: @escaping (T) -> U) -> (T) -> V {
return { f(g($0)) }
}
infix operator >>>
infix operator <<<
let pt1 = view(_1)((1, 2))
print(pt1) // CHECK-NEXT: 1
let pt2 = over(_1)({ $0 * 4 })((1, 2))
print(pt2) // CHECK-NEXT: (4, 2)
let pt3 = set(_1)(3)((1, 2))
print(pt3) // CHECK-NEXT: (3, 2)
let pt4 = view(_2)(("hello", 5))
print(pt4) // CHECK-NEXT: 5
|