Advertisement
Guest User

Untitled

a guest
Feb 23rd, 2019
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.01 KB | None | 0 0
  1. import Foundation
  2. import XCTest
  3.  
  4. protocol Semiring {
  5. static func + (lhs: Self, rhs: Self) -> Self
  6. static func * (lhs: Self, rhs: Self) -> Self
  7. static var zero: Self { get }
  8. static var one: Self { get }
  9. }
  10.  
  11. extension Int: Semiring {
  12. static let zero = 0
  13. static let one = 1
  14. }
  15.  
  16. extension Bool: Semiring {
  17. static func + (lhs: Bool, rhs: Bool) -> Bool {
  18. return lhs || rhs
  19. }
  20.  
  21. static func * (lhs: Bool, rhs: Bool) -> Bool {
  22. return lhs && rhs
  23. }
  24.  
  25. static let zero = false
  26. static let one = true
  27. }
  28.  
  29. struct FunctionS<A, S: Semiring> {
  30. let execute: (A) -> S
  31.  
  32. init(_ execute: @escaping (A) -> S) {
  33. self.execute = execute
  34. }
  35. }
  36.  
  37. extension FunctionS: Semiring {
  38. static func + (lhs: FunctionS, rhs: FunctionS) -> FunctionS {
  39. return FunctionS { lhs.execute($0) + rhs.execute($0) }
  40. }
  41.  
  42. static func * (lhs: FunctionS, rhs: FunctionS) -> FunctionS {
  43. return FunctionS { lhs.execute($0) * rhs.execute($0) }
  44. }
  45.  
  46. static var zero: FunctionS {
  47. return FunctionS { _ in S.zero }
  48. }
  49.  
  50. static var one: FunctionS {
  51. return FunctionS { _ in S.one }
  52. }
  53. }
  54.  
  55. typealias Predicate<A> = FunctionS<A, Bool>
  56.  
  57. prefix func ! <A> (p: Predicate<A>) -> Predicate<A> {
  58. return .init { !p.execute($0) }
  59. }
  60.  
  61. func equalTo<T: Equatable>(_ value: T) -> Predicate<T> {
  62. return Predicate<T> { $0 == value }
  63. }
  64.  
  65. func greaterThan<T: Comparable>(_ value: T) -> Predicate<T> {
  66. return Predicate<T> { $0 > value }
  67. }
  68.  
  69. func lessThan<T: Comparable>(_ value: T) -> Predicate<T> {
  70. return Predicate<T> { $0 < value }
  71. }
  72.  
  73. func || <A> (lhs: Predicate<A>, rhs: Predicate<A>) -> Predicate<A> {
  74. return lhs + rhs
  75. }
  76.  
  77. func && <A> (lhs: Predicate<A>, rhs: Predicate<A>) -> Predicate<A> {
  78. return lhs * rhs
  79. }
  80.  
  81. lessThan(5).execute(0) // true
  82.  
  83. extension Comparable {
  84. func `is`(_ predicate: Predicate<Self>) -> Bool {
  85. return predicate.execute(self)
  86. }
  87. }
  88.  
  89. func between<T: Comparable>(_ a: T, and b: T) -> Predicate<T> {
  90. return greaterThan(a) && lessThan(b)
  91. }
  92.  
  93. let valid = between(1, and: 5) && !equalTo(3)
  94. 1.is(valid) // false -- outside of range
  95. 2.is(valid) // true -- in range and not equalTo 3
  96. 3.is(valid) // false -- is equalTo
  97. 4.is(valid) // true -- in range and not equalTo 3
  98. 5.is(valid) // false -- outside of range
  99. 5.is(!valid) // true -- inverse of previous
  100.  
  101. extension Sequence {
  102. func filtered(by predicate: Predicate<Element>) -> [Element] {
  103. return filter(predicate.execute)
  104. }
  105. }
  106. [0, 2, 3, 6].filtered(by: valid) // [2]
  107.  
  108. extension FunctionS {
  109. func apply(_ f: @escaping (A) -> A) -> FunctionS<A, S> {
  110. return .init { self.execute(f($0)) }
  111. }
  112. }
  113.  
  114. let validNegative: Predicate<Int> = valid.apply(-)
  115. (-2).is(validNegative) // true
  116.  
  117. let validIfHalved = valid.apply { $0 / 2 }
  118. 4.is(validIfHalved) // validates 2
  119.  
  120. let validIfDoubled = valid.apply { $0 * 2 }
  121. 2.is(validIfDoubled) // validates 4
  122.  
  123. extension Comparable {
  124. func assert(_ predicate: Predicate<Self>, file: StaticString = #file, line: UInt = #line) {
  125. XCTAssertTrue(self.is(predicate), file: file, line: line)
  126. }
  127. }
  128. extension Sequence where Element: Comparable {
  129. func assert(_ predicate: Predicate<Element>, file: StaticString = #file, line: UInt = #line) {
  130. for element in self {
  131. element.assert(predicate, file: file, line: line)
  132. }
  133. }
  134. }
  135.  
  136. func testMinimumIsValid() {
  137. 2.assert(valid) // runs single test using comparable method
  138. }
  139.  
  140. func testNumbersAreValid() {
  141. [2, 4].assert(valid) // runs 2 tests using sequence method
  142. }
  143.  
  144. func testNumbersAreInvalid() {
  145. [1, 3, 5].assert(!valid) // runs 3 tests using sequence method
  146. }
  147.  
  148. func isNil<T>() -> Predicate<T?> {
  149. return Predicate { $0 == nil }
  150. }
  151.  
  152. func isNotNil<T>() -> Predicate<T?> {
  153. return Predicate { $0 != nil }
  154. }
  155.  
  156. extension Optional {
  157. func assert(_ predicate: Predicate<Wrapped?>, file: StaticString = #file, line: UInt = #line) {
  158. XCTAssertTrue(predicate.execute(self), file: file, line: line)
  159. }
  160. }
  161.  
  162. let optional: Int? = 1
  163. optional.assert(!isNil())
  164. optional.assert(isNotNil())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement