Skip to content

Instantly share code, notes, and snippets.

@y-yu
Created August 8, 2017 19:01
Show Gist options
  • Save y-yu/b528b9751541a5a51f81c0e128427ca3 to your computer and use it in GitHub Desktop.
Save y-yu/b528b9751541a5a51f81c0e128427ca3 to your computer and use it in GitHub Desktop.
Higher Kinded Polymorphism in Swift
class App<T, A> {
var underlying: Any
init(_ a: Any) {
underlying = a
}
}
protocol Newtype1 {
associatedtype A
associatedtype T
func inj() -> App<T, A>
}
extension Newtype1 {
func inj() -> App<T, A> {
return App(self)
}
}
class ArrayConstructor { }
extension Array: Newtype1 {
typealias A = Element
typealias T = ArrayConstructor
}
extension App where T: ArrayConstructor {
func prj() -> Array<A> {
return (self.underlying as! Array<A>)
}
}
indirect enum Tree<Element> {
case Leaf
case Node(l: Tree<Element>, a: Element, r: Tree<Element>)
func pp() -> String {
switch self {
case .Leaf:
return "L"
case let .Node(l, a, r):
return "N(\(l.pp()), \(a), \(r.pp()))"
}
}
}
class TreeConstructor { }
extension Tree: Newtype1 {
typealias A = Element
typealias T = TreeConstructor
}
extension App where T: TreeConstructor {
func prj() -> Tree<A> {
return (self.underlying as! Tree<A>)
}
}
protocol Functor {
associatedtype F
associatedtype E
func mapF<B>(_ f: (E) -> B) -> App<F, B>
}
extension Array: Functor {
typealias F = ArrayConstructor
typealias E = Element
func mapF<B>(_ f: (E) -> B) -> App<F, B> {
return self.map(f).inj()
}
}
extension Tree: Functor {
typealias F = TreeConstructor
typealias E = Element
func loop<B>(_ x: Tree<E>, _ f: (E) -> B) -> Tree<B> {
switch x {
case .Leaf:
return .Leaf
case let .Node(l, a, r):
return Tree<B>.Node(l: loop(l, f), a: f(a), r: loop(r, f))
}
}
func mapF<B>(_ f: (E) -> B) -> App<F, B> {
return loop(self, f).inj()
}
}
print( [1, 2, 3, 4, 5].mapF({ (x: Int) -> Int in return x + 1 }).prj() )
print( Tree<Int>.Node(l: .Node(l: .Leaf, a: 1, r: .Leaf), a: 2, r: .Node(l: .Leaf, a: 3, r: .Leaf)).mapF({ (x: Int) -> Int in return x + 1 }).prj().pp() )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment