fork download
  1. protocol HTraverse {
  2. associatedtype Source: HList
  3.  
  4. func traverse(_ f: () -> Void) -> HNil
  5. }
  6.  
  7. extension HCons: HTraverse where T: HTraverse {
  8. typealias Source = HCons<H, T>
  9.  
  10. func traverse(_ f: () -> Void) -> HNil {
  11. f()
  12. return self.tail.traverse(f)
  13. }
  14. }
  15.  
  16. extension HNil: HTraverse {
  17. typealias Source = HNil
  18.  
  19. public func traverse(_ f: () -> Void) -> HNil {
  20. f()
  21. return HNil()
  22. }
  23. }
  24.  
  25. public protocol Providable {
  26. associatedtype S
  27.  
  28. static func provide() -> State<S, Self>
  29. }
  30.  
  31. precedencegroup Right {
  32. associativity: right
  33. }
  34.  
  35. infix operator >>>: Right
  36.  
  37. public func >>><S, A, T: HList>(_ ma: State<S, A>, _ mb: State<S, T>) -> State<S, HCons<A, T>> {
  38. return ma.flatMap {
  39. (a: A) -> State<S, HCons<A, T>> in
  40. mb.map {
  41. (t: T) -> HCons<A, T> in HCons<A, T>(a, t)
  42. }
  43. }
  44. }
  45.  
  46. public func end<S>() -> State<S, HNil> {
  47. return State<S, HNil> {
  48. s -> (HNil, S) in (HNil(), s)
  49. }
  50. }
  51.  
  52. extension Array: Providable where Element: Providable, Element.S == Int {
  53. public typealias S = Int
  54.  
  55. public static func provide() -> State<Int, Array<Element>> {
  56. return Element.provide().map { e -> Array<Element> in [e] }
  57. }
  58. }
  59.  
  60. extension Bool: Providable {
  61. public typealias S = Int
  62.  
  63. public static func provide() -> State<Int, Bool> {
  64. return State<Int, Bool> {
  65. s -> (Bool, Int) in
  66. if (s % 2 == 0) {
  67. return (true, s + 1)
  68. } else {
  69. return (false, s + 1)
  70. }
  71. }
  72. }
  73. }
  74.  
  75. extension Int: Providable {
  76. public typealias S = Int
  77.  
  78. public static func provide() -> State<Int, Int> {
  79. return State<Int, Int>{
  80. (s: Int) -> (Int, Int) in (s, s + 1)
  81. }
  82. }
  83. }
  84.  
  85. extension Optional: Providable where Wrapped: Providable, Wrapped.S == Int {
  86. public typealias S = Int
  87.  
  88. public static func provide() -> State<Int, Optional<Wrapped>> {
  89. return State<Int, Optional<Wrapped>> {
  90. s -> (Optional<Wrapped>, Int) in
  91. if (s % 2 == 0) {
  92. return Wrapped.provide().map { w -> Optional<Wrapped> in .some(w) }.run(s)
  93. } else {
  94. return (.none, s + 1)
  95. }
  96. }
  97. }
  98. }
  99.  
  100. extension String: Providable {
  101. public typealias S = Int
  102.  
  103. public static func provide() -> State<Int, String> {
  104. return State<Int, String> {
  105. (s: Int) -> (String, Int) in (String(s), s + 1)
  106. }
  107. }
  108. }
  109.  
  110. public struct State<S, A> {
  111. public let run : (S) -> (A, S)
  112.  
  113. public init(_ run : @escaping (S) -> (A, S)) {
  114. self.run = run
  115. }
  116.  
  117. func eval(_ s: S) -> A {
  118. let (a, _) = self.run(s)
  119. return a
  120. }
  121.  
  122. func flatMap<B>(_ f: @escaping (A) -> State<S, B>) -> State<S, B> {
  123. return State<S, B> {
  124. (s: S) -> (B, S) in
  125. let (a, s1) = self.run(s)
  126. return f(a).run(s1)
  127. }
  128. }
  129.  
  130. func map<B>(_ f: @escaping (A) -> B) -> State<S, B> {
  131. return State<S, B> {
  132. (s: S) -> (B, S) in
  133. let (a, s1) = self.run(s)
  134. return (f(a), s1)
  135. }
  136. }
  137. }
  138.  
  139. public protocol HList { }
  140.  
  141. public struct HNil: HList {
  142. init() { }
  143.  
  144. static let hNil = HNil()
  145. }
  146.  
  147. public struct HCons<H, T: HList>: HList {
  148. public let head: H
  149. public let tail: T
  150.  
  151. public init(_ h: H, _ t: T) {
  152. self.head = h
  153. self.tail = t
  154. }
  155. }
  156.  
  157. let a =
  158. String.provide() >>>
  159. Bool.provide() >>>
  160. Bool.provide() >>>
  161. Int.provide() >>>
  162. Optional<Int>.provide() >>>
  163. String.provide() >>>
  164. Bool.provide() >>>
  165. Bool.provide() >>>
  166. Int.provide() >>>
  167. Optional<Int>.provide() >>>
  168. end()
  169.  
  170. var counter = 0
  171.  
  172. let _ = a.eval(0).traverse { () -> Void in
  173. print(counter)
  174. counter = counter + 1
  175. }
  176.  
Success #stdin #stdout 0s 7588KB
stdin
Standard input is empty
stdout
0
1
2
3
4
5
6
7
8
9
10