Skip to content

Commit

Permalink
Merge pull request #6 from CodaFi/contemplated-alias
Browse files Browse the repository at this point in the history
Solve our polymorphic typealias problem
  • Loading branch information
pthariensflame committed Aug 19, 2015
2 parents 8aebd98 + 1ba44b4 commit d84ae7f
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 101 deletions.
16 changes: 8 additions & 8 deletions Aquifer/Auxiliary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Swiftz

/// Lifts an arrow into a pipe by connecting its inputs to the upstream input and its outputs to the
/// downstream output of the pipe.
public func arr<A, B, R>(f: A -> B) -> Proxy<(), A, (), B, R> {
public func arr<A, B, R>(f: A -> B) -> Pipe<A, B, R>.T {
return map(f)
}

Expand All @@ -21,7 +21,7 @@ public func arr<A, B, R>(f: A -> B) -> Proxy<(), A, (), B, R> {
/// Values sent along the upstream input in a `.Left` will appear downstream in a `.Left` after the
/// pipe has operated on them. Values appearing along the upstream input in a `.Right` will appear
/// downstream in a `.Right` unchanged.
public func left<A, B, C, R>(p: Proxy<(), A, (), B, R>) -> Proxy<(), Either<A, C>, (), Either<B, C>, R> {
public func left<A, B, C, R>(p: Pipe<A, B, R>.T) -> Pipe<Either<A, C>, Either<B, C>, R>.T {
return leftInner() >~ for_(p) { v in yield(Either.Left(v)) }
}

Expand All @@ -30,7 +30,7 @@ public func left<A, B, C, R>(p: Proxy<(), A, (), B, R>) -> Proxy<(), Either<A, C
/// Values sent along the upstream input in a `.Right` will appear downstream in a `.Right` after
/// the pipe has operated on them. Values appearing along the upstream input in a `.Left` will
/// appear downstream in a `.Left` unchanged.
public func right<A, B, C, R>(p: Proxy<(), A, (), B, R>) -> Proxy<(), Either<C, A>, (), Either<C, B>, R> {
public func right<A, B, C, R>(p: Pipe<A, B, R>.T) -> Pipe<Either<C, A>, Either<C, B>, R>.T {
return rightInner() >~ for_(p) { v in yield(Either.Right(v)) }
}

Expand All @@ -44,7 +44,7 @@ precedence 180
/// `.Left` values fed to the pipe's upstream input will appear downstream as `.Left`s that have
/// been operated on by the first pipe. `.Right` values fed to the pipe's upstream input will
/// appear downstream as `.Right`s that have been operated on by the second pipe.
public func +++ <A, B, C, D, R>(p: Proxy<(), A, (), B, R>, q: Proxy<(), C, (), D, R>) -> Proxy<(), Either<A, C>, (), Either<B, D>, R> {
public func +++ <A, B, C, D, R>(p: Pipe<A, B, R>.T, q: Pipe<C, D, R>.T) -> Pipe<Either<A, C>, Either<B, D>, R>.T {
return left(p) >-> right(q)
}

Expand All @@ -59,19 +59,19 @@ public func mapOutput<UO, UI, DI, DO, NO, FR>(p: Proxy<UO, UI, DI, DO, FR>, _ f:
}

/// Yields a pipe that produces left-scanned values with the given step function.
public func scan1i<DT, FR>(stepWith step: (DT, DT) -> DT) -> Proxy<(), DT, (), DT, FR> {
public func scan1i<DT, FR>(stepWith step: (DT, DT) -> DT) -> Pipe<DT, DT, FR>.T {
return scan1(stepWith: step, initializeWith: identity, extractWith: identity)
}

/// Yields a pipe that produces left-scanned values with the given step function. The pipe is not
/// required to have an initial value, but one is expected to be produced by the `initial` function.
public func scan1<A, UI, DO, FR>(stepWith step: (A, UI) -> A, initializeWith initial: UI -> A, extractWith extractor: A -> DO) -> Proxy<(), UI, (), DO, FR> {
public func scan1<A, UI, DO, FR>(stepWith step: (A, UI) -> A, initializeWith initial: UI -> A, extractWith extractor: A -> DO) -> Pipe<UI, DO, FR>.T {
return await() >>- { scan(stepWith: step, initializeWith: initial($0), extractWith: extractor) }
}

// MARK: - Implementation Details Follow

private func leftInner<A, B, C>() -> Proxy<(), Either<A, C>, (), Either<B, C>, A> {
private func leftInner<A, B, C>() -> Pipe<Either<A, C>, Either<B, C>, A>.T {
return await() >>- {
switch $0 {
case let .Left(x): return pure(x)
Expand All @@ -81,7 +81,7 @@ private func leftInner<A, B, C>() -> Proxy<(), Either<A, C>, (), Either<B, C>, A
}


private func rightInner<A, B, C>() -> Proxy<(), Either<C, A>, (), Either<C, B>, A> {
private func rightInner<A, B, C>() -> Pipe<Either<C, A>, Either<C, B>, A>.T {
return await() >>- {
switch $0 {
case let .Left(x): return yield(Either.Left(x)) >>- { _ in rightInner() }
Expand Down
78 changes: 39 additions & 39 deletions Aquifer/Basic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,28 @@ public func drain<UI, DI, DO, FR>() -> Proxy<(), UI, DI, DO, FR> {
}

/// Returns a `Pipe` that applies a (side-effecting) action to all values flowing downstream.
public func chain<DT, FR>(action: DT -> Void) -> Proxy<(), DT, (), DT, FR> {
public func chain<DT, FR>(action: DT -> Void) -> Pipe<DT, DT, FR>.T {
return for_(cat()) { action($0); return yield($0) }
}

// MARK: - Data.Bool

/// Returns a `Pipe` that negates any `Bool`ean input flowing downstream.
public func not<FR>() -> Proxy<(), Bool, (), Bool, FR> {
public func not<FR>() -> Pipe<Bool, Bool, FR>.T {
return map(!)
}

// MARK: - Data.Monoid

/// Folds the values inside the given pipe using the `Monoid` op.
public func mconcat<V: Monoid>(p: Proxy<X, (), (), V, ()>) -> V {
public func mconcat<V: Monoid>(p: Producer<V, ()>.T) -> V {
return fold(p, stepWith: { $0.op($1) }, initializeWith: V.mempty, extractWith: { $0 })
}

/// Mark: - Data.Foldable

/// Returns a representation of the given pipe as a list.
public func toList<V>(p: Proxy<X, (), (), V, ()>) -> List<V> {
public func toList<V>(p: Producer<V, ()>.T) -> List<V> {
return toListRepr(p.repr)
}

Expand All @@ -53,15 +53,15 @@ public func toList<V>(p: Proxy<X, (), (), V, ()>) -> List<V> {
// MARK: Basics

/// Returns the first element in the given pipe, if it exists.
public func head<V>(p: Proxy<X, (), (), V, ()>) -> V? {
public func head<V>(p: Producer<V, ()>.T) -> V? {
switch next(p) {
case .Left(_): return nil
case let .Right(k): return k.0
}
}

/// Returns the last element in the given pipe, if it exists.
public func last<V>(p: Proxy<X, (), (), V, ()>) -> V? {
public func last<V>(p: Producer<V, ()>.T) -> V? {
switch next(p) {
case .Left(_): return nil
case let .Right((dO, q)):
Expand All @@ -70,90 +70,90 @@ public func last<V>(p: Proxy<X, (), (), V, ()>) -> V? {
}

/// Returns whether the given pipe has terminated.
public func isEmpty<V>(p: Proxy<X, (), (), V, ()>) -> Bool {
public func isEmpty<V>(p: Producer<V, ()>.T) -> Bool {
return next(p).isLeft
}

/// Counts the number of elements in the given pipe.
public func length<V>(p: Proxy<X, (), (), V, ()>) -> Int {
public func length<V>(p: Producer<V, ()>.T) -> Int {
return fold(p, stepWith: { n, _ in n + 1 }, initializeWith: 0, extractWith: { $0 })
}

// MARK: Transformations

/// Returns a pipe that applies the given function to all values flowing downstream.
public func map<UI, DO, FR>(f: UI -> DO) -> Proxy<(), UI, (), DO, FR> {
public func map<UI, DO, FR>(f: UI -> DO) -> Pipe<UI, DO, FR>.T {
return for_(cat()) { v in yield(f(v)) }
}

/// Returns a pipe that uses the given function to produce sequences that are subsequently flattened
/// downstream.
public func mapMany<UI, S: SequenceType, FR>(f: UI -> S) -> Proxy<(), UI, (), S.Generator.Element, FR> {
public func mapMany<UI, S: SequenceType, FR>(f: UI -> S) -> Pipe<UI, S.Generator.Element, FR>.T {
return for_(cat()) { each(f($0)) }
}

/// Returns a pipe that yields the description of each value flowing downstream.
public func description<UI: CustomStringConvertible, FR>() -> Proxy<(), UI, (), String, FR> {
public func description<UI: CustomStringConvertible, FR>() -> Pipe<UI, String, FR>.T {
return map { $0.description }
}

/// Returns a pipe that yields the debug description of each value flowing downstream.
public func debugDescription<UI: CustomDebugStringConvertible, FR>() -> Proxy<(), UI, (), String, FR> {
public func debugDescription<UI: CustomDebugStringConvertible, FR>() -> Pipe<UI, String, FR>.T {
return map { $0.debugDescription }
}

// MARK: Folds

/// Folds over the elements of the given `Producer`.
public func fold<A, V, R>(p: Proxy<X, (), (), V, ()>, stepWith step: (A, V) -> A, initializeWith initial: A, extractWith extractor: A -> R) -> R {
public func fold<A, V, R>(p: Producer<V, ()>.T, stepWith step: (A, V) -> A, initializeWith initial: A, extractWith extractor: A -> R) -> R {
return foldRepr(p.repr, stepWith: step, initializeWith: initial, extractWith: extractor)
}

/// A version of `fold` that preserve the return value of the given `Producer`.
public func foldRet<A, V, FR, R>(p: Proxy<X, (), (), V, FR>, stepWith step: (A, V) -> A, initializeWith initial: A, extractWith extractor: A -> R) -> (R, FR) {
public func foldRet<A, V, FR, R>(p: Producer<V, FR>.T, stepWith step: (A, V) -> A, initializeWith initial: A, extractWith extractor: A -> R) -> (R, FR) {
return foldRetRepr(p.repr, stepWith: step, initializeWith: initial, extractWith: extractor)
}

// MARK: Special Folds

/// Returns a pipe that flattens the elements of any sequences flowing downstream.
public func concat<S: SequenceType, FR>() -> Proxy<(), S, (), S.Generator.Element, FR> {
public func concat<S: SequenceType, FR>() -> Pipe<S, S.Generator.Element, FR>.T {
return for_(cat(), each)
}


/// Returns whether all elements of the receiver satisfy the given predicate.
public func all<V>(p: Proxy<X, (), (), V, ()>, predicate: V -> Bool) -> Bool {
public func all<V>(p: Producer<V, ()>.T, predicate: V -> Bool) -> Bool {
return isEmpty(p >-> filter { !predicate($0) })
}

/// Returns whether any element of the receiver satisfies the given predicate.
public func any<V>(p: Proxy<X, (), (), V, ()>, predicate: V -> Bool) -> Bool {
public func any<V>(p: Producer<V, ()>.T, predicate: V -> Bool) -> Bool {
return !isEmpty(p >-> filter(predicate))
}

/// Returns the conjunct of all values inside the pipe.
public func and(p: Proxy<X, (), (), Bool, ()>) -> Bool {
public func and(p: Producer<Bool, ()>.T) -> Bool {
return all(p) { b in b }
}

/// Returns the disjunct of all values inside the pipe.
public func or(p: Proxy<X, (), (), Bool, ()>) -> Bool {
public func or(p: Producer<Bool, ()>.T) -> Bool {
return any(p) { b in b }
}

/// Returns the sum of the values in the given pipe.
public func sum<V: NumericType>(p: Proxy<X, (), (), V, ()>) -> V {
public func sum<V: NumericType>(p: Producer<V, ()>.T) -> V {
return fold(p, stepWith: { $0.plus($1) }, initializeWith: V.zero, extractWith: { $0 })
}

/// Returns the product of the values in the given pipe.
public func product<V: NumericType>(p: Proxy<X, (), (), V, ()>) -> V {
public func product<V: NumericType>(p: Producer<V, ()>.T) -> V {
return fold(p, stepWith: { $0.times($1) }, initializeWith: V.one, extractWith: { $0 })
}

/// Finds the maximum value among all the elements of the given pipe.
public func maximum<V: Comparable>(p: Proxy<X, (), (), V, ()>) -> V? {
public func maximum<V: Comparable>(p: Producer<V, ()>.T) -> V? {
func step(x: V?, _ v: V) -> V? {
if let w = x {
return max(v, w)
Expand All @@ -165,7 +165,7 @@ public func maximum<V: Comparable>(p: Proxy<X, (), (), V, ()>) -> V? {
}

/// Finds the minimum value among all the elements of the given pipe.
public func minimum<V: Comparable>(p: Proxy<X, (), (), V, ()>) -> V? {
public func minimum<V: Comparable>(p: Producer<V, ()>.T) -> V? {
func step(x: V?, _ v: V) -> V? {
if let w = x {
return min(v, w)
Expand All @@ -179,7 +179,7 @@ public func minimum<V: Comparable>(p: Proxy<X, (), (), V, ()>) -> V? {
// MARK: Scans

/// Returns a pipe that uses the given function as a left-scan on all values flowing downstream.
public func scan<A, UI, DO, FR>(stepWith step: (A, UI) -> A, initializeWith initial: A, extractWith extractor: A -> DO) -> Proxy<(), UI, (), DO, FR> {
public func scan<A, UI, DO, FR>(stepWith step: (A, UI) -> A, initializeWith initial: A, extractWith extractor: A -> DO) -> Pipe<UI, DO, FR>.T {
return yield(extractor(initial)) >>- { _ in await() >>- { scan(stepWith: step, initializeWith: step(initial, $0), extractWith: extractor) } }
}

Expand Down Expand Up @@ -218,12 +218,12 @@ public func takeWhile<DT>(predicate: DT -> Bool) -> Proxy<(), DT, (), DT, ()> {
}

/// Returns a `Pipe` that discards a given amount of values.
public func drop<DT, FR>(n: Int) -> Proxy<(), DT, (), DT, FR> {
public func drop<DT, FR>(n: Int) -> Pipe<DT, DT, FR>.T {
return dropInner(n) >>- { _ in cat() }
}

/// Returns a `Pipe` that discards values as long as the given predicate is true.
public func dropWhile<DT, FR>(predicate: DT -> Bool) -> Proxy<(), DT, (), DT, FR> {
public func dropWhile<DT, FR>(predicate: DT -> Bool) -> Pipe<DT, DT, FR>.T {
return await() >>- { v in
if predicate(v) {
return dropWhile(predicate)
Expand All @@ -236,24 +236,24 @@ public func dropWhile<DT, FR>(predicate: DT -> Bool) -> Proxy<(), DT, (), DT, FR
// MARK: Searching with Equality

/// Returns whether a given value matches any of the values inside the given pipe.
public func elem<V: Equatable>(p: Proxy<X, (), (), V, ()>, _ x: V) -> Bool {
public func elem<V: Equatable>(p: Producer<V, ()>.T, _ x: V) -> Bool {
return any(p) { x == $0 }
}

/// Returns whether a given value does not match any of the values inside the given pipe.
public func notElem<V: Equatable>(p: Proxy<X, (), (), V, ()>, _ x: V) -> Bool {
public func notElem<V: Equatable>(p: Producer<V, ()>.T, _ x: V) -> Bool {
return all(p) { x != $0 }
}

// MARK: Searching with Predicates

/// Finds the first element in the pipe that satisfies a given predicate.
public func find<V>(p: Proxy<X, (), (), V, ()>, _ predicate: V -> Bool) -> V? {
public func find<V>(p: Producer<V, ()>.T, _ predicate: V -> Bool) -> V? {
return head(p >-> filter(predicate))
}

/// Returns a `Pipe` that only forwards values that satisfy the given predicate.
public func filter<DT, FR>(predicate: DT -> Bool) -> Proxy<(), DT, (), DT, FR> {
public func filter<DT, FR>(predicate: DT -> Bool) -> Pipe<DT, DT, FR>.T {
return for_(cat()) { v in
if predicate(v) {
return yield(v)
Expand All @@ -266,31 +266,31 @@ public func filter<DT, FR>(predicate: DT -> Bool) -> Proxy<(), DT, (), DT, FR> {
// MARK: Indexing

/// Returns a pipe that outputs the indices of all elements that match the given element
public func elemIndices<UI: Equatable, FR>(@autoclosure(escaping) x: () -> UI) -> Proxy<(), UI, (), Int, FR> {
public func elemIndices<UI: Equatable, FR>(@autoclosure(escaping) x: () -> UI) -> Pipe<UI, Int, FR>.T {
return findIndices { x() == $0 }
}

/// Finds the index of the first element in the pipe that satisfies a given predicate.
public func findIndex<V>(p: Proxy<X, (), (), V, ()>, _ predicate: V -> Bool) -> Int? {
public func findIndex<V>(p: Producer<V, ()>.T, _ predicate: V -> Bool) -> Int? {
return head(p >-> findIndices(predicate))
}

/// Returns a pipe that outputs the indices of all elements that match the given predicate.
public func findIndices<UI, FR>(predicate: UI -> Bool) -> Proxy<(), UI, (), Int, FR> {
public func findIndices<UI, FR>(predicate: UI -> Bool) -> Pipe<UI, Int, FR>.T {
return findIndicesInner(predicate, 0)
}

// MARK: Zipping

/// Returns a `Producer` of pairs that zips the downstream output of the two given `Producer`s
/// together.
public func zip<V0, V1, R>(p: Proxy<X, (), (), V0, R>, _ q: Proxy<X, (), (), V1, R>) -> Proxy<X, (), (), (V0, V1), R> {
public func zip<V0, V1, R>(p: Producer<V0, R>.T, _ q: Producer<V1, R>.T) -> Producer<(V0, V1), R>.T {
return zipWith(p, q) { ($0, $1) }
}

/// Returns a `Producer` of values that zips the downstream output of the two given pipes together
/// using the given function.
public func zipWith<V0, V1, V2, R>(p: Proxy<X, (), (), V0, R>, _ q: Proxy<X, (), (), V1, R>, _ f: (V0, V1) -> V2) -> Proxy<X, (), (), V2, R> {
public func zipWith<V0, V1, V2, R>(p: Producer<V0, R>.T, _ q: Producer<V1, R>.T, _ f: (V0, V1) -> V2) -> Producer<V2, R>.T {
switch next(p) {
case let .Left(x): return pure(x)
case let .Right((dO0, r)):
Expand All @@ -303,11 +303,11 @@ public func zipWith<V0, V1, V2, R>(p: Proxy<X, (), (), V0, R>, _ q: Proxy<X, (),
}

// this seems to required higher-kinded types to implement, even though none appear in its signature
/*public func tee<V, R>(p: Proxy<(), V, (), X, R>) -> Proxy<(), V, (), V, R> {
/*public func tee<V, R>(p: Pipe<V, X, R>.T) -> Pipe<V, V, R>.T {
}*/

// this seems to required higher-kinded types to implement, even though none appear in its signature
/*public func generalize<UT, UI, DO, FR>(p: Proxy<(), UI, (), DO, FR>) -> Proxy<UT, UI, UT, DO, FR> {
/*public func generalize<UT, UI, DO, FR>(p: Pipe<UI, DO, FR>.T) -> Proxy<UT, UI, UT, DO, FR> {
}*/

// MARK: - Implementation Details Follow
Expand All @@ -320,7 +320,7 @@ private func dropInner<DT>(n: Int) -> Proxy<(), DT, (), DT, ()> {
}
}

private func findIndicesInner<UI, FR>(predicate: UI -> Bool, _ n: Int) -> Proxy<(), UI, (), Int, FR> {
private func findIndicesInner<UI, FR>(predicate: UI -> Bool, _ n: Int) -> Pipe<UI, Int, FR>.T {
return await() >>- {
if predicate($0) {
return yield(n) >>- { _ in findIndicesInner(predicate, n + 1) }
Expand All @@ -346,7 +346,7 @@ private func foldRetRepr<A, V, FR, R>(p: ProxyRepr<X, (), (), V, FR>, stepWith s
}
}

private func lastInner<V>(x: V, _ p: Proxy<X, (), (), V, ()>) -> V? {
private func lastInner<V>(x: V, _ p: Producer<V, ()>.T) -> V? {
switch next(p) {
case .Left(_): return x
case let .Right((dO, q)):
Expand Down
Loading

0 comments on commit d84ae7f

Please sign in to comment.