Skip to content

Commit

Permalink
Merge pull request #1 from CodaFi/vacuum
Browse files Browse the repository at this point in the history
Initial Commit
  • Loading branch information
CodaFi committed Jul 5, 2015
2 parents 610edfa + eb16dbb commit 3cc4b30
Show file tree
Hide file tree
Showing 17 changed files with 1,676 additions and 1 deletion.
670 changes: 670 additions & 0 deletions Focus.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions Focus.xcodeproj/project.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

89 changes: 89 additions & 0 deletions Focus/ArrayZipper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//
// ArrayZipper.swift
// swiftz
//
// Created by Alexander Ronald Altman on 8/4/14.
// Copyright (c) 2014 Maxwell Swadling. All rights reserved.
//

/// A zipper for arrays. Zippers are convenient ways of traversing and modifying the parts of a
/// structure using a cursor to focus on its individual parts.
public struct ArrayZipper<A> : ArrayLiteralConvertible {
typealias Element = A

/// The underlying array of values.
public let values : [A]
/// The position of the cursor within the Array.
public let position : Int

public init(_ values : [A] = [], _ position : Int = 0) {
if position < 0 {
self.position = 0
} else if position >= values.count {
self.position = values.count - 1
} else {
self.position = position
}
self.values = values
}

/// Creates an ArrayZipper pointing at the head of a given list of elements.
public init(arrayLiteral elements : Element...) {
self.init(elements, 0)
}

/// Creates an `ArrayZipper` with the cursor adjusted by n in the direction of the sign of the
/// given value.
public func move(n : Int = 1) -> ArrayZipper<A> {
return ArrayZipper(values, position + n)
}

/// Creates an `ArrayZipper` with the cursor set to a given position value.
public func moveTo(pos : Int) -> ArrayZipper<A> {
return ArrayZipper(values, pos)
}

/// Returns whether the cursor of the receiver is at the end of its underlying Array.
public var isAtEnd : Bool {
return position >= (values.count - 1)
}
}

extension ArrayZipper /*: Functor*/ {
typealias B = Any
typealias FB = ArrayZipper<B>

public func fmap<B>(f : A -> B) -> ArrayZipper<B> {
return ArrayZipper<B>(self.values.map(f), self.position)
}
}

public func <^> <A, B>(f : A -> B, xz : ArrayZipper<A>) -> ArrayZipper<B> {
return xz.fmap(f)
}

extension ArrayZipper /*: Copointed*/ {
/// Extracts the value at the position of the receiver's cursor.
///
/// This function is not total, but makes the guarantee that if `zipper.isAtEnd` returns false,
/// it is safe to call.
public func extract() -> A {
return self.values[self.position]
}
}

extension ArrayZipper /*: Comonad*/ {
typealias FFA = ArrayZipper<ArrayZipper<A>>

public func duplicate() -> ArrayZipper<ArrayZipper<A>> {
return ArrayZipper<ArrayZipper<A>>((0 ..< self.values.count).map { ArrayZipper(self.values, $0) }, self.position)
}

public func extend<B>(f : ArrayZipper<A> -> B) -> ArrayZipper<B> {
return ArrayZipper<B>((0 ..< self.values.count).map { f(ArrayZipper(self.values, $0)) }, self.position)
}
}

public func ->> <A, B>(xz : ArrayZipper<A>, f: ArrayZipper<A> -> B) -> ArrayZipper<B> {
return xz.extend(f)
}
19 changes: 19 additions & 0 deletions Focus/Focus.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Focus.h
// Focus
//
// Created by Robert Widmann on 7/2/15.
// Copyright © 2015 TypeLift. All rights reserved.
//

#import <Cocoa/Cocoa.h>

//! Project version number for Focus.
FOUNDATION_EXPORT double FocusVersionNumber;

//! Project version string for Focus.
FOUNDATION_EXPORT const unsigned char FocusVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <Focus/PublicHeader.h>


28 changes: 28 additions & 0 deletions Focus/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2015 TypeLift. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
54 changes: 54 additions & 0 deletions Focus/Iso.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// Iso.swift
// swiftz
//
// Created by Alexander Ronald Altman on 7/22/14.
// Copyright (c) 2015 TypeLift. All rights reserved.
//

/// Captures an isomorphism between S and A.
///
/// :param: S The source of the Iso heading right
/// :param: T The target of the Iso heading left
/// :param: A The source of the Iso heading right
/// :param: B The target of the Iso heading left
public struct Iso<S, T, A, B> {
public let get : S -> A
public let inject : B -> T

/// Builds an Iso from a pair of inverse functions.
public init(get : S -> A, inject : B -> T) {
self.get = get
self.inject = inject
}

/// Runs a value of type `S` along both parts of the Iso.
public func modify(v : S, _ f : A -> B) -> T {
return inject(f(get(v)))
}

/// Composes an `Iso` with the receiver.
public func compose<I, J>(i2 : Iso<A, B, I, J>) -> Iso<S, T, I, J> {
return self i2
}

/// Converts an Iso to a Lens.
public var asLens : Lens<S, T, A, B> {
return Lens { s in IxStore(self.get(s)) { self.inject($0) } }
}

/// Converts an Iso to a Prism with a getter that always succeeds..
public var asPrism : Prism<S, T, A, B> {
return Prism(tryGet: { .Some(self.get($0)) }, inject: inject)
}
}

/// The identity isomorphism.
public func identity<S, T>() -> Iso<S, T, S, T> {
return Iso(get: identity, inject: identity)
}

/// Compose isomorphisms.
public func <S, T, I, J, A, B>(i1 : Iso<S, T, I, J>, i2 : Iso<I, J, A, B>) -> Iso<S, T, A, B> {
return Iso(get: i2.get i1.get, inject: i1.inject i2.inject)
}
89 changes: 89 additions & 0 deletions Focus/IxCont.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//
// IxCont.swift
// swiftz
//
// Created by Alexander Ronald Altman on 6/10/14.
// Copyright (c) 2015 TypeLift. All rights reserved.
//

/// `IxCont` is the Continuation Monad indexed by a result type `R`, an immediate output type `O`
/// and a value `A`.
public struct IxCont<R, O, A> {
/// Lowers an `IxCont` to an indexed continuation function.
public let run : (A -> O) -> R

/// Lifts an indexed continuation function into an `IxCont`.
public init(_ run : (A -> O) -> R) {
self.run = run
}

/// Applies a function that transforms the input value of the continuation function.
public func map<B>(f : A -> B) -> IxCont<R, O, B> {
return f <^> self
}

/// Applies a function that transforms the final output value of the continuation function.
public func imap<S>(f : R -> S) -> IxCont<S, O, A> {
return f <^^> self
}

/// Applies a function that transforms the immediate output value of the continuation function.
public func contramap<N>(f : N -> O) -> IxCont<R, N, A> {
return f <!> self
}

/// Composes two continuation functions by applying the final result of the second to the
/// immediate value of the first then running both continuations in series.
public func ap<E, B>(f : IxCont<E, R, A -> B>) -> IxCont<E, O, B> {
return f <*> self
}

/// Fits the receiver together with a second continuation and runs them in series.
public func flatMap<E, B>(f : A -> IxCont<O, E, B>) -> IxCont<R, E, B> {
return self >>- f
}
}

public func run<R, O>(a : IxCont<R, O, O>) -> R {
return a.run(identity)
}

public func pure<R, A>(x : A) -> IxCont<R, R, A> {
return IxCont { $0(x) }
}

public func <^> <R, O, A, B>(f : A -> B, a: IxCont<R, O, A>) -> IxCont<R, O, B> {
return IxCont { k in a.run { k(f($0)) } }
}

public func <^^> <R, S, O, A>(f : R -> S, a: IxCont<R, O, A>) -> IxCont<S, O, A> {
return IxCont { f(a.run($0)) }
}

public func <!> <R, N, O, A>(f : N -> O, a: IxCont<R, O, A>) -> IxCont<R, N, A> {
return IxCont { k in a.run { f(k($0)) } }
}

public func <*> <R, I, O, A, B>(f : IxCont<R, I, A -> B>, a: IxCont<I, O, A>) -> IxCont<R, O, B> {
return IxCont { k in f.run { g in a.run { k(g($0)) } } }
}

public func >>- <R, I, O, A, B>(a : IxCont<R, I, A>, f: A -> IxCont<I, O, B>) -> IxCont<R, O, B> {
return IxCont { k in a.run { f($0).run(k) } }
}

public func join<R, I, O, A>(a : IxCont<R, I, IxCont<I, O, A>>) -> IxCont<R, O, A> {
return IxCont { k in a.run { $0.run(k) } }
}

public func shift<R, I, J, O, A>(f : (A -> IxCont<I, I, O>) -> IxCont<R, J, J>) -> IxCont<R, O, A> {
return IxCont { k in run(f { pure(k($0)) }) }
}

public func reset<R, O, A>(a : IxCont<A, O, O>) -> IxCont<R, R, A> {
return pure(run(a))
}

public func callCC<R, O, A, B>(f : (A -> IxCont<O, O, B>) -> IxCont<R, O, A>) -> IxCont<R, O, A> {
return IxCont { k in (f { x in IxCont { _ in k(x) } }).run(k) }
}
104 changes: 104 additions & 0 deletions Focus/IxMultiStore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//
// IxMultiStore.swift
// swiftz
//
// Created by Alexander Ronald Altman on 8/4/14.
// Copyright (c) 2015 TypeLift. All rights reserved.
//

/// The Store Comonad Transformer indexed by a position type `O` and the ArrayZipper Comonad.
public struct IxMultiStore<O, I, A> {
/// The current position of the receiver.
let pos : O

/// Retrieves a zipper that focuses on functions that retrieve values at index I.
let set : ArrayZipper<I -> A>

public init(_ pos: O, _ set: ArrayZipper<I -> A>) {
self.pos = pos
self.set = set
}

/// Applies a function to the retrieval of values.
public func map<B>(f : A -> B) -> IxMultiStore<O, I, B> {
return f <^> self
}

/// Applies a function to the position indexes that can be focused on by the underlying zipper.
public func imap<P>(f : O -> P) -> IxMultiStore<P, I, A> {
return f <^^> self
}

/// Applies a function to the retrieval indexes of the underlying zipper.
public func contramap<H>(f : H -> I) -> IxMultiStore<O, H, A> {
return f <!> self
}

/// Returns an `IxStore` that retrieves an `IxStore` for every index in the receiver.
public func duplicate<J>() -> IxMultiStore<O, J, IxMultiStore<J, I, A>> {
return IxMultiStore<O, J, IxMultiStore<J, I, A>>(pos, set ->> { g in { IxMultiStore<J, I, A>($0, g) } })
}

/// Extends the context of the store with a function that retrieves values from another store
/// indexed by a different position.
public func extend<E, B>(f : IxMultiStore<E, I, A> -> B) -> IxMultiStore<O, E, B> {
return self ->> f
}

/// Extracts a zipper that focuses on all values at a given index.
public func put(x : I) -> ArrayZipper<A> {
return { $0(x) } <^> set
}

/// Extracts a zipper that focuses on all values at an index given by applying a function to the
/// receiver's position index.
public func puts(f : O -> I) -> ArrayZipper<A> {
return put(f(pos))
}

/// Extracts the first focused value from the store at a given index.
public func peek(x : I) -> A {
return put(x).extract()
}

/// Extracts the first focused value from the store at an index given by applying a function to
/// the receiver's position index.
public func peeks(f : O -> I) -> A {
return peek(f(pos))
}

/// Returns a new `IxMultiStore` with its position index set to the given value.
public func seek<P>(x : P) -> IxMultiStore<P, I, A> {
return IxMultiStore<P, I, A>(x, set)
}

/// Returns a new `IxMultiStore` with its position index set to the result of applying the given
/// function to the current position index.
public func seeks<P>(f : O -> P) -> IxMultiStore<P, I, A> {
return IxMultiStore<P, I, A>(f(pos), set)
}
}

public func extract<I, A>(a : IxMultiStore<I, I, A>) -> A {
return a.set.extract()(a.pos)
}

public func <^> <O, I, A, B>(f : A -> B, a : IxMultiStore<O, I, A>) -> IxMultiStore<O, I, B> {
return IxMultiStore(a.pos, { g in { f(g($0)) } } <^> a.set)
}

public func<^^><O, P, I, A>(f : O -> P, a : IxMultiStore<O, I, A>) -> IxMultiStore<P, I, A> {
return IxMultiStore(f(a.pos), a.set)
}

public func <!> <O, H, I, A>(f : H -> I, a : IxMultiStore<O, I, A>) -> IxMultiStore<O, H, A> {
return IxMultiStore(a.pos, { $0 f } <^> a.set)
}

public func ->> <O, J, I, A, B>(a : IxMultiStore<O, I, A>, f : IxMultiStore<J, I, A> -> B) -> IxMultiStore<O, J, B> {
return IxMultiStore(a.pos, a.set ->> { g in { f(IxMultiStore($0, g)) } })
}

public func lower<I, A>(a : IxMultiStore<I, I, A>) -> ArrayZipper<A> {
return { $0(a.pos) } <^> a.set
}
Loading

0 comments on commit 3cc4b30

Please sign in to comment.