protocol HTraverse {
associatedtype Source: HList
func traverse(_ f: () -> Void) -> HNil
}
extension HCons: HTraverse where T: HTraverse {
typealias Source = HCons<H, T>
func traverse(_ f: () -> Void) -> HNil {
f()
return self.tail.traverse(f)
}
}
extension HNil: HTraverse {
typealias Source = HNil
public func traverse(_ f: () -> Void) -> HNil {
f()
return HNil()
}
}
public protocol Providable {
associatedtype S
static func provide() -> State<S, Self>
}
precedencegroup Right {
associativity: right
}
infix operator >>>: Right
public func >>><S, A, T: HList>(_ ma: State<S, A>, _ mb: State<S, T>) -> State<S, HCons<A, T>> {
return ma.flatMap {
(a: A) -> State<S, HCons<A, T>> in
mb.map {
(t: T) -> HCons<A, T> in HCons<A, T>(a, t)
}
}
}
public func end<S>() -> State<S, HNil> {
return State<S, HNil> {
s -> (HNil, S) in (HNil(), s)
}
}
extension Array: Providable where Element: Providable, Element.S == Int {
public typealias S = Int
public static func provide() -> State<Int, Array<Element>> {
return Element.provide().map { e -> Array<Element> in [e] }
}
}
extension Bool: Providable {
public typealias S = Int
public static func provide() -> State<Int, Bool> {
return State<Int, Bool> {
s -> (Bool, Int) in
if (s % 2 == 0) {
return (true, s + 1)
} else {
return (false, s + 1)
}
}
}
}
extension Int: Providable {
public typealias S = Int
public static func provide() -> State<Int, Int> {
return State<Int, Int>{
(s: Int) -> (Int, Int) in (s, s + 1)
}
}
}
extension Optional: Providable where Wrapped: Providable, Wrapped.S == Int {
public typealias S = Int
public static func provide() -> State<Int, Optional<Wrapped>> {
return State<Int, Optional<Wrapped>> {
s -> (Optional<Wrapped>, Int) in
if (s % 2 == 0) {
return Wrapped.provide().map { w -> Optional<Wrapped> in .some(w) }.run(s)
} else {
return (.none, s + 1)
}
}
}
}
extension String: Providable {
public typealias S = Int
public static func provide() -> State<Int, String> {
return State<Int, String> {
(s: Int) -> (String, Int) in (String(s), s + 1)
}
}
}
public struct State<S, A> {
public let run : (S) -> (A, S)
public init(_ run : @escaping (S) -> (A, S)) {
self.run = run
}
func eval(_ s: S) -> A {
let (a, _) = self.run(s)
return a
}
func flatMap<B>(_ f: @escaping (A) -> State<S, B>) -> State<S, B> {
return State<S, B> {
(s: S) -> (B, S) in
let (a, s1) = self.run(s)
return f(a).run(s1)
}
}
func map<B>(_ f: @escaping (A) -> B) -> State<S, B> {
return State<S, B> {
(s: S) -> (B, S) in
let (a, s1) = self.run(s)
return (f(a), s1)
}
}
}
public protocol HList { }
public struct HNil: HList {
init() { }
static let hNil = HNil()
}
public struct HCons<H, T: HList>: HList {
public let head: H
public let tail: T
public init(_ h: H, _ t: T) {
self.head = h
self.tail = t
}
}
let a =
String.provide() >>>
Bool.provide() >>>
Bool.provide() >>>
Int.provide() >>>
Optional<Int>.provide() >>>
String.provide() >>>
Bool.provide() >>>
Bool.provide() >>>
Int.provide() >>>
Optional<Int>.provide() >>>
end()
var counter = 0
let _ = a.eval(0).traverse { () -> Void in
print(counter)
counter = counter + 1
}
cHJvdG9jb2wgSFRyYXZlcnNlIHsKICAgIGFzc29jaWF0ZWR0eXBlIFNvdXJjZTogSExpc3QKICAgCiAgICBmdW5jIHRyYXZlcnNlKF8gZjogKCkgLT4gVm9pZCkgLT4gSE5pbAp9CgpleHRlbnNpb24gSENvbnM6IEhUcmF2ZXJzZSB3aGVyZSBUOiBIVHJhdmVyc2UgewogICAgdHlwZWFsaWFzIFNvdXJjZSA9IEhDb25zPEgsIFQ+CiAgIAogICAgZnVuYyB0cmF2ZXJzZShfIGY6ICgpIC0+IFZvaWQpIC0+IEhOaWwgewogICAgICAgIGYoKQogICAgICAgIHJldHVybiBzZWxmLnRhaWwudHJhdmVyc2UoZikKICAgIH0KfQoKZXh0ZW5zaW9uIEhOaWw6IEhUcmF2ZXJzZSB7CiAgICB0eXBlYWxpYXMgU291cmNlID0gSE5pbAogICAKICAgIHB1YmxpYyBmdW5jIHRyYXZlcnNlKF8gZjogKCkgLT4gVm9pZCkgLT4gSE5pbCB7CiAgICAgICAgZigpCiAgICAgICAgcmV0dXJuIEhOaWwoKQogICAgfQp9CgpwdWJsaWMgcHJvdG9jb2wgUHJvdmlkYWJsZSB7CiAgICBhc3NvY2lhdGVkdHlwZSBTCiAgICAKICAgIHN0YXRpYyBmdW5jIHByb3ZpZGUoKSAtPiBTdGF0ZTxTLCBTZWxmPgp9CgpwcmVjZWRlbmNlZ3JvdXAgUmlnaHQgewogICAgYXNzb2NpYXRpdml0eTogcmlnaHQKfQoKaW5maXggb3BlcmF0b3IgPj4+OiBSaWdodAoKcHVibGljIGZ1bmMgPj4+PFMsIEEsIFQ6IEhMaXN0PihfIG1hOiBTdGF0ZTxTLCBBPiwgXyBtYjogU3RhdGU8UywgVD4pIC0+IFN0YXRlPFMsIEhDb25zPEEsIFQ+PiB7CiAgICByZXR1cm4gbWEuZmxhdE1hcCB7CiAgICAgICAgKGE6IEEpIC0+IFN0YXRlPFMsIEhDb25zPEEsIFQ+PiBpbgogICAgICAgICAgICBtYi5tYXAgewogICAgICAgICAgICAgICAgKHQ6IFQpIC0+IEhDb25zPEEsIFQ+IGluIEhDb25zPEEsIFQ+KGEsIHQpCiAgICAgICAgICAgIH0KICAgIH0KfQoKcHVibGljIGZ1bmMgZW5kPFM+KCkgLT4gU3RhdGU8UywgSE5pbD4gewogICAgcmV0dXJuIFN0YXRlPFMsIEhOaWw+IHsKICAgICAgICBzIC0+IChITmlsLCBTKSBpbiAoSE5pbCgpLCBzKQogICAgfQp9CgpleHRlbnNpb24gQXJyYXk6IFByb3ZpZGFibGUgd2hlcmUgRWxlbWVudDogUHJvdmlkYWJsZSwgRWxlbWVudC5TID09IEludCB7CiAgICBwdWJsaWMgdHlwZWFsaWFzIFMgPSBJbnQKICAgIAogICAgcHVibGljIHN0YXRpYyBmdW5jIHByb3ZpZGUoKSAtPiBTdGF0ZTxJbnQsIEFycmF5PEVsZW1lbnQ+PiB7CiAgICAgICAgcmV0dXJuIEVsZW1lbnQucHJvdmlkZSgpLm1hcCB7IGUgLT4gQXJyYXk8RWxlbWVudD4gaW4gW2VdIH0KICAgIH0KfQoKZXh0ZW5zaW9uIEJvb2w6IFByb3ZpZGFibGUgewogICAgcHVibGljIHR5cGVhbGlhcyBTID0gSW50CiAgICAKICAgIHB1YmxpYyBzdGF0aWMgZnVuYyBwcm92aWRlKCkgLT4gU3RhdGU8SW50LCBCb29sPiB7CiAgICAgICAgcmV0dXJuIFN0YXRlPEludCwgQm9vbD4gewogICAgICAgICAgICBzIC0+IChCb29sLCBJbnQpIGluCiAgICAgICAgICAgICAgICBpZiAocyAlIDIgPT0gMCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiAodHJ1ZSwgcyArIDEpCiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHJldHVybiAoZmFsc2UsIHMgKyAxKQogICAgICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKZXh0ZW5zaW9uIEludDogUHJvdmlkYWJsZSB7CiAgICBwdWJsaWMgdHlwZWFsaWFzIFMgPSBJbnQKICAgIAogICAgcHVibGljIHN0YXRpYyBmdW5jIHByb3ZpZGUoKSAtPiBTdGF0ZTxJbnQsIEludD4gewogICAgICAgIHJldHVybiBTdGF0ZTxJbnQsIEludD57CiAgICAgICAgICAgIChzOiBJbnQpIC0+IChJbnQsIEludCkgaW4gKHMsIHMgKyAxKQogICAgICAgIH0KICAgIH0KfQoKZXh0ZW5zaW9uIE9wdGlvbmFsOiBQcm92aWRhYmxlIHdoZXJlIFdyYXBwZWQ6IFByb3ZpZGFibGUsIFdyYXBwZWQuUyA9PSBJbnQgewogICAgcHVibGljIHR5cGVhbGlhcyBTID0gSW50CiAgICAKICAgIHB1YmxpYyBzdGF0aWMgZnVuYyBwcm92aWRlKCkgLT4gU3RhdGU8SW50LCBPcHRpb25hbDxXcmFwcGVkPj4gewogICAgICAgIHJldHVybiBTdGF0ZTxJbnQsIE9wdGlvbmFsPFdyYXBwZWQ+PiB7CiAgICAgICAgICAgIHMgLT4gKE9wdGlvbmFsPFdyYXBwZWQ+LCBJbnQpIGluCiAgICAgICAgICAgICAgICBpZiAocyAlIDIgPT0gMCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBXcmFwcGVkLnByb3ZpZGUoKS5tYXAgeyB3IC0+IE9wdGlvbmFsPFdyYXBwZWQ+IGluIC5zb21lKHcpIH0ucnVuKHMpCiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHJldHVybiAoLm5vbmUsIHMgKyAxKQogICAgICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKZXh0ZW5zaW9uIFN0cmluZzogUHJvdmlkYWJsZSB7CiAgICBwdWJsaWMgdHlwZWFsaWFzIFMgPSBJbnQKICAgIAogICAgcHVibGljIHN0YXRpYyBmdW5jIHByb3ZpZGUoKSAtPiBTdGF0ZTxJbnQsIFN0cmluZz4gewogICAgICAgIHJldHVybiBTdGF0ZTxJbnQsIFN0cmluZz4gewogICAgICAgICAgICAoczogSW50KSAtPiAoU3RyaW5nLCBJbnQpIGluIChTdHJpbmcocyksIHMgKyAxKQogICAgICAgIH0KICAgIH0KfQoKcHVibGljIHN0cnVjdCBTdGF0ZTxTLCBBPiB7CiAgICBwdWJsaWMgbGV0IHJ1biA6IChTKSAtPiAoQSwgUykKICAgIAogICAgcHVibGljIGluaXQoXyBydW4gOiBAZXNjYXBpbmcgKFMpIC0+IChBLCBTKSkgewogICAgICAgIHNlbGYucnVuID0gcnVuCiAgICB9CiAgICAKICAgIGZ1bmMgZXZhbChfIHM6IFMpIC0+IEEgewogICAgICAgIGxldCAoYSwgXykgPSBzZWxmLnJ1bihzKQogICAgICAgIHJldHVybiBhCiAgICB9CiAgICAKICAgIGZ1bmMgZmxhdE1hcDxCPihfIGY6IEBlc2NhcGluZyAoQSkgLT4gU3RhdGU8UywgQj4pIC0+IFN0YXRlPFMsIEI+IHsKICAgICAgICByZXR1cm4gU3RhdGU8UywgQj4gewogICAgICAgICAgICAoczogUykgLT4gKEIsIFMpIGluCiAgICAgICAgICAgICAgICBsZXQgKGEsIHMxKSA9IHNlbGYucnVuKHMpCiAgICAgICAgICAgICAgICByZXR1cm4gZihhKS5ydW4oczEpCiAgICAgICAgfQogICAgfQogICAgCiAgICBmdW5jIG1hcDxCPihfIGY6IEBlc2NhcGluZyAoQSkgLT4gQikgLT4gU3RhdGU8UywgQj4gewogICAgICAgIHJldHVybiBTdGF0ZTxTLCBCPiB7CiAgICAgICAgICAgIChzOiBTKSAtPiAoQiwgUykgaW4KICAgICAgICAgICAgICAgIGxldCAoYSwgczEpID0gc2VsZi5ydW4ocykKICAgICAgICAgICAgICAgIHJldHVybiAoZihhKSwgczEpCiAgICAgICAgfQogICAgfQp9CgpwdWJsaWMgcHJvdG9jb2wgSExpc3QgeyB9CgpwdWJsaWMgc3RydWN0IEhOaWw6IEhMaXN0IHsKICAgIGluaXQoKSB7IH0KICAgIAogICAgc3RhdGljIGxldCBoTmlsID0gSE5pbCgpCn0KCnB1YmxpYyBzdHJ1Y3QgSENvbnM8SCwgVDogSExpc3Q+OiBITGlzdCB7CiAgICBwdWJsaWMgbGV0IGhlYWQ6IEgKICAgIHB1YmxpYyBsZXQgdGFpbDogVAoKICAgIHB1YmxpYyBpbml0KF8gaDogSCwgXyB0OiBUKSB7CiAgICAgICAgc2VsZi5oZWFkID0gaAogICAgICAgIHNlbGYudGFpbCA9IHQKICAgIH0KfQoKbGV0IGEgPQogICAgU3RyaW5nLnByb3ZpZGUoKSA+Pj4KICAgIEJvb2wucHJvdmlkZSgpID4+PgogICAgQm9vbC5wcm92aWRlKCkgPj4+CiAgICBJbnQucHJvdmlkZSgpID4+PgogICAgT3B0aW9uYWw8SW50Pi5wcm92aWRlKCkgPj4+CiAgICBTdHJpbmcucHJvdmlkZSgpID4+PgogICAgQm9vbC5wcm92aWRlKCkgPj4+CiAgICBCb29sLnByb3ZpZGUoKSA+Pj4KICAgIEludC5wcm92aWRlKCkgPj4+CiAgICBPcHRpb25hbDxJbnQ+LnByb3ZpZGUoKSA+Pj4KICAgIGVuZCgpCgp2YXIgY291bnRlciA9IDAKCmxldCBfID0gYS5ldmFsKDApLnRyYXZlcnNlIHsgKCkgLT4gVm9pZCBpbgogICAgcHJpbnQoY291bnRlcikKICAgIGNvdW50ZXIgPSBjb3VudGVyICsgMQp9Cg==