Created
August 8, 2017 19:01
-
-
Save y-yu/b528b9751541a5a51f81c0e128427ca3 to your computer and use it in GitHub Desktop.
Higher Kinded Polymorphism in Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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