Skip to content

Instantly share code, notes, and snippets.

@gregomni
Created April 20, 2018 18:08
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 gregomni/a1f8364cea0272066cfd645285e72c43 to your computer and use it in GitHub Desktop.
Save gregomni/a1f8364cea0272066cfd645285e72c43 to your computer and use it in GitHub Desktop.
Array counts in the type system...
protocol Counted {
associatedtype More : Counted
associatedtype Less : Counted where Self.More.Less == Self
}
struct CountedArray<T, C: Counted> {
var array: [T]
init(array: [T] = []) {
self.array = array
}
func appending(_ elem: T) -> CountedArray<T, C.More> {
return CountedArray<T, C.More>(array: array + [elem])
}
func dropFirst() -> CountedArray<T, C.Less> {
return CountedArray<T, C.Less>(array: Array(array.dropFirst(1)))
}
}
typealias CountedZero<T: Counted> = T
typealias CountedOne<T: Counted> = T.More
typealias CountedTwo<T: Counted> = T.More.More
typealias CountedThree<T: Counted> = T.More.More.More
func addTwo<Zero: Counted>(_: Zero, _ x: CountedArray<Int, CountedTwo<Zero>>) -> Int {
return x.array[0] + x.array[1]
}
func doStuff<Zero: Counted>(_ counter: Zero, array: CountedArray<Int, Zero>) {
let a = array.appending(3)
_ = addTwo(counter, a) // cannot invoke 'addTwo'
let b = a.appending(4)
_ = addTwo(counter, b) // ok
let c = b.appending(5)
_ = addTwo(counter, c) // cannot invoke 'addTwo'
let d = c.dropFirst()
_ = addTwo(counter, d) // ok
let e = d.dropFirst()
_ = addTwo(counter, e) // cannot invoke 'addTwo'
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment