Skip to content

Instantly share code, notes, and snippets.

@adamkuipers
Last active December 8, 2015 19:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamkuipers/bb7bdb9cc425de8905c7 to your computer and use it in GitHub Desktop.
Save adamkuipers/bb7bdb9cc425de8905c7 to your computer and use it in GitHub Desktop.
Higher-kinded types encoded as path-dependent types
// Based off of https://gist.github.com/runarorama/33986541f0f1ddf4a3c7
protocol λ {
typealias α
}
struct K<L: λ>: λ {
typealias α = L.α
}
protocol Each: λ {
typealias α: λ
typealias A = K<α>.α
static func foreach(x: α, f: A -> Void)
}
extension Optional: λ {
typealias α = Wrapped
}
struct OptionalEach<Wrapped>: Each {
typealias α = Optional<Wrapped>
static func foreach(x: α, f: Wrapped -> Void) {
if let e = x {
f(e)
}
}
}
extension Array: λ {
typealias α = Element
}
struct ArrayEach<Element>: Each {
typealias α = Array<Element>
static func foreach(x: α, f: Element -> Void) {
x.forEach(f)
}
}
ArrayEach<Int>.foreach([1,2,3]) { print($0) }
OptionalEach<String>.foreach("a") { print($0) }
OptionalEach<String>.foreach(nil) { print($0) }
protocol HasEach: λ {
typealias E: Each
}
extension Array: HasEach {
typealias E = ArrayEach<Element>
}
// Can't figure out how to get the typeclass to resolve for global functions.
func foreach<X: HasEach>(x: X, f: X.α -> Void) {
X.E.foreach(x, f: f)
}
// Compiler Error:
// error: cannot convert value of type 'X.α -> Void' to expected argument type '_ -> Void'
// X.E.foreach(x, f: f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment