Skip to content

Instantly share code, notes, and snippets.

@jarsen jarsen/Pipeline.swift
Last active Aug 29, 2015

Embed
What would you like to do?
// Playground - noun: a place where people can play
import UIKit
import CoreGraphics
public enum Result<T> {
case Success(@autoclosure () -> T)
case Failure(String)
init(_ value:T) {
self = .Success(value)
}
}
extension Result {
public func bind<U>(f: T -> Result<U>) -> Result<U> {
switch self {
case let .Success(value):
return f(value())
case let .Failure(error):
return .Failure(error)
}
}
public func fmap<U>(f: T->U) -> Result<U> {
switch self {
case let .Success(value):
return .Success(f(value()))
case let .Failure(error):
return .Failure(error)
}
}
public func forceUnwrap() -> T {
switch self {
case let .Success(value):
return value()
case let .Failure:
assertionFailure("You force unwrapped \(self), which was not a Result.Success")
}
}
}
infix operator |> { precedence 50 associativity left }
// MARK: Curry
public func curry<A, B, Z>(f: (A, B) -> Z) -> A -> B -> Z {
return { a in { b in f(a, b) } }
}
public func curry<A, B, C, Z>(f: (A, B, C) -> Z) -> A -> B -> C -> Z {
return { a in { b in { c in f(a, b, c) } } }
}
public func curry<A, B, C, D, Z>(f: (A, B, C, D) -> Z) -> A -> B -> C -> D -> Z {
return { a in { b in { c in { d in f(a, b, c, d) } } } }
}
public func curry<A, B, C, D, E, Z>(f: (A, B, C, D, E) -> Z) -> A -> B -> C -> D -> E -> Z {
return { a in { b in { c in { d in { e in f(a, b, c, d, e) } } } } }
}
// MARK: Reverse Curry
public func reverseCurry<A, B, Z>(f: (A, B) -> Z) -> B -> A -> Z {
return { b in { a in f(a, b) } }
}
public func reverseCurry<A, B, C, Z>(f: (A, B, C) -> Z) -> C -> B -> A -> Z {
return {c in { b in { a in f(a, b, c) } } }
}
public func reverseCurry<A, B, C, D, Z>(f: (A, B, C, D) -> Z) -> D -> C -> B -> A -> Z {
return { d in { c in { b in { a in f(a, b, c, d) } } } }
}
public func reverseCurry<A, B, C, D, E, Z>(f: (A, B, C, D, E) -> Z) -> E -> D -> C -> B -> A -> Z {
return { e in { d in { c in { b in { a in f(a, b, c, d, e) } } } } }
}
// MARK: Pipeline
public func |> <A,Z>(lhs: A, rhs: A -> Z) -> Z {
return rhs(lhs)
}
public func |> <A,B,Z>(lhs: A, rhs: ((A, B) -> Z, B)) -> Z {
return rhs.0(lhs, rhs.1)
}
public func |> <A,B,C,Z>(lhs: A, rhs: (((A, B, C) -> Z), B, C)) -> Z {
return rhs.0(lhs, rhs.1, rhs.2)
}
// MARK: Optional Pipeline
public func |> <A, Z>(lhs: A?, rhs: A -> Z) -> Z? {
return map(lhs, rhs)
}
public func |> <A, B, Z>(lhs: A?, rhs: ((A, B) -> Z, B)) -> Z? {
return map(lhs, reverseCurry(rhs.0)(rhs.1))
}
public func |> <A,B,C,Z>(lhs: A?, rhs: (((A, B, C) -> Z), B, C)) -> Z? {
return map(lhs, reverseCurry(rhs.0)(rhs.2)(rhs.1))
}
// MARK: Result Pipeline
public func |> <A,Z>(lhs: Result<A>, rhs: A -> Z) -> Result<Z> {
return lhs.fmap(rhs)
}
public func |> <A,B,Z>(lhs: Result<A>, rhs: ((A, B) -> Z, B)) -> Result<Z> {
return lhs.fmap(reverseCurry(rhs.0)(rhs.1))
}
public func |> <A,B,C,Z>(lhs: Result<A>, rhs: (((A, B, C) -> Z), B, C)) -> Result<Z> {
return lhs.fmap(reverseCurry(rhs.0)(rhs.2)(rhs.1))
}
// MARK: Examples
func increment(int: Int) -> Int {
return int + 1
}
2 |> increment
// clear, concise, and functional, but only works on arrays.
// does not generalize to Sequence
let example1 = [1,2,3,4,5].filter({$0 % 2 == 0}).map({$0 * 3}).reduce(0, +)
example1
// this is dirtier than example1, but generalized to Sequence
let example2 = reduce(map(filter([1,2,3,4,5], {$0 % 2 == 0}), {$0 * 3}), 0, +)
example2
// works on sequences and clean
let example3 = [1,2,3,4,5]
|> (filter, {$0 % 2 == 0})
|> (map, {$0 * 3})
|> (reduce, 0, +)
example3
// Optional examples
let elements = [2, 4, 6, 8, 10]
let isEvenIndex = find(elements, 6) |> { $0 % 2 == 0} // "Found 6 at index 2"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.