Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save SiarheiFedartsou/6161b3d89d0172be0b398a75e65859af to your computer and use it in GitHub Desktop.

Select an option

Save SiarheiFedartsou/6161b3d89d0172be0b398a75e65859af to your computer and use it in GitHub Desktop.
//: Playground - noun: a place where people can play
import UIKit
protocol StageProtocol {
associatedtype StageIn
associatedtype StageOut
}
class Stage<In, Out> : StageProtocol {
typealias StageIn = In
typealias StageOut = Out
}
protocol StageHeadProtocol : StageProtocol {}
class StageHead<In, Out> : Stage<In, Out>, StageHeadProtocol {
let mapper: (In) -> Out
init(mapper: @escaping (In) -> Out) {
self.mapper = mapper
}
}
protocol IntermediateStageProtocol : StageProtocol {
associatedtype PrevStage : StageProtocol
var previousStage: PrevStage { get }
}
class IntermediateStage<In, Out, PreviousStage: StageProtocol> : Stage<In, Out>, IntermediateStageProtocol where PreviousStage.StageOut == In {
typealias PrevStage = PreviousStage
let mapper: (In) -> Out
init(mapper: @escaping (In) -> Out, previousStage: PreviousStage) {
self.mapper = mapper
self.previousStage = previousStage
}
let previousStage: PreviousStage
}
func first<T: StageHeadProtocol>(_ stage: T) -> T {
return stage
}
func first<T: IntermediateStageProtocol, U>(_ stage: T) -> U where T.PrevStage : StageHeadProtocol, U == T.PrevStage {
return stage.previousStage
}
func first<T: IntermediateStageProtocol, U>(_ stage: T) -> U where T.PrevStage : IntermediateStageProtocol, T.PrevStage.PrevStage : StageHeadProtocol, U == T.PrevStage.PrevStage {
return stage.previousStage.previousStage
}
func first<T: IntermediateStageProtocol, U>(_ stage: T) -> U where T.PrevStage : IntermediateStageProtocol, T.PrevStage.PrevStage : IntermediateStageProtocol, T.PrevStage.PrevStage.PrevStage : StageHeadProtocol, U == T.PrevStage.PrevStage.PrevStage {
return stage.previousStage.previousStage.previousStage
}
let head = StageHead(mapper: { (x: Int) -> (Int) in return x * x })
first(head).mapper(10)
let next1 = IntermediateStage(mapper: { (x: Int) -> (Int) in return x + 1 }, previousStage: head)
first(next1).mapper(10)
let next2 = IntermediateStage(mapper: { (x: Int) -> (Int) in return x + 42 }, previousStage: next1)
first(next2).mapper(10)
let next3 = IntermediateStage(mapper: { (x: Int) -> (String) in return "\(x)" }, previousStage: next2)
first(next3).mapper(10)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment