Skip to content

Instantly share code, notes, and snippets.

@CodaFi
Last active August 29, 2015 14:04
Show Gist options
  • Save CodaFi/f179603d4fde6911fa75 to your computer and use it in GitHub Desktop.
Save CodaFi/f179603d4fde6911fa75 to your computer and use it in GitHub Desktop.
// Playground - noun: a place where people can play
//
// Needle Scratch
/// Swift does not have a notion of pattern matching, at least as supported by the language itself.
/// What it does have are Sum Types with associated fields, otherwise known as (a poor man's, in this
/// case) variant records. Switch statements allow for a measure of destructuring and pattern matching. Exploiting
/// this, one can write pattern matching as a switch statement against one of these "matchers" of the
/// correct arity.
public enum LiftMatch<T> {
case Match(T)
}
public enum LiftMatch2<T, U> {
case Match(T, U)
}
public enum LiftMatch3<T, U, V> {
case Match(T, U, V)
}
public enum LiftMatch4<T, U, V, W> {
case Match(T, U, V, W)
}
public enum LiftMatch5<T, U, V, W, X> {
case Match(T, U, V, W, X)
}
public enum LiftMatch6<T, U, V, W, X, Y> {
case Match(T, U, V, W, X, Y)
}
public enum LiftMatch7<T, U, V, W, X, Y, Z> {
case Match(T, U, V, W, X, Y, Z)
}
public enum LiftMatch8<S, T, U, V, W, X, Y, Z> {
case Match(S, T, U, V, W, X, Y, Z)
}
public enum LiftMatch9<R, S, T, U, V, W, X, Y, Z> {
case Match(R, S, T, U, V, W, X, Y, Z)
}
public enum LiftMatch10<Q, R, S, T, U, V, W, X, Y, Z> {
case Match(Q, R, T, U, V, S, W, X, Y, Z)
}
/// Custom front-append operator
infix operator +> {}
func +><C>(lhs : C, rhs : [C]) -> [C] {
var x = Array<C>(rhs)
x.insert(lhs, atIndex:0)
return x
}
func ~= <T: Comparable>(left: Array<T>, right: Array<T>) -> Bool {
return left == right
}
func zipWith<A : Comparable, B : Comparable, C>(f : (A -> B -> C), l1 : [A], l2 : [B]) -> [C] {
switch LiftMatch3.Match(f, l1, l2) {
case .Match(_, [], _):
return []
case .Match(_, _, []):
return []
case .Match(let f, let l1, let l2):
return f(l1[0])(l2[0]) +> zipWith(f, Array<A>(l1[1..<l1.count]), Array<B>(l2[1..<l2.count]))
default:
assert(false, "Non-exhaustive pattern match performed")
}
}
/// Select the proper overloading of plus... Swift still cant infer that from the type
/// signature. *sigh*
func plus(x : Int) -> Int -> Int {
return { (let y : Int) -> Int in
return x + y
}
}
zipWith(plus, [1, 2, 3], [1, 2, 3]) // [2, 4, 6]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment