Last active
August 29, 2015 14:04
-
-
Save CodaFi/f179603d4fde6911fa75 to your computer and use it in GitHub Desktop.
This file contains 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
// 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