Skip to content

Commit 8774c4e

Browse files
committed
Merge pull request #17 from typelift/readme-and-weep
Readme and Weep
2 parents 03eabb7 + 01dc2ab commit 8774c4e

File tree

1 file changed

+152
-4
lines changed

1 file changed

+152
-4
lines changed

README.md

Lines changed: 152 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,169 @@
33
Basis
44
=====
55

6-
The Basis is an exploration of pure declarative programming and reasoning in Swift. It by no means contains idiomatic code, but is instead intended to be a repository for structures and ideas grounded in theory and mathematics. Present in this repository are the necessary components to handle system interaction, control, data flow, and a number of extensions and improvements to the Swift Standard Library and its structures. Higher-level APIs and structures are generally excluded from the Basis to be implemented in other libraries.
6+
The Basis is an exploration of pure declarative programming and reasoning in
7+
Swift. It by no means contains idiomatic code, but is instead intended to be a
8+
repository for structures and ideas grounded in theory and mathematics. Present
9+
in this repository are the necessary components to handle system interaction,
10+
control, data flow, and a number of extensions and improvements to the Swift
11+
Standard Library and its structures. Higher-level APIs and structures are
12+
generally excluded from the Basis to be implemented in other libraries.
713

814

915
It Gets Better!
1016
===============
1117

12-
Swift provides an excellent opportunity to not just witness, but actually understand, the formalization of many seemingly "complex" and abstract algebraic structures without having to learn Haskell or ML or any of the other famous FP languages. The documentation of types in this repository serves as a way to de-serialize a lot of the complex terms and jargon you may come across in these languages. If, for any reason, the documentation is too dense or unreadable, it means this library is failing one of its unit tests! Clarification or rewrites of documentation to serve the broader community are a priority and a promise. Any questions or comments should be made into issues, or pull requests if you feel you can word it better.
18+
Swift provides an excellent opportunity to not just witness, but actually
19+
understand the formalization of many seemingly "complex" and abstract algebraic
20+
structures without having to learn Haskell or ML or any of the other famous FP
21+
languages. The documentation of types in this repository serves as a way to
22+
de-serialize a lot of the complex terms and jargon you may come across in these
23+
languages. If, for any reason, the documentation is too dense or unreadable, it
24+
means this library is failing one of its unit tests! Clarification or rewrites
25+
of documentation to serve the broader community are a priority and a promise.
26+
Any questions or comments should be made into issues, or pull requests if you
27+
feel you can word it better.
1328

1429
Let's make the world a bit less scary.
1530

1631
Getting Started
1732
===============
1833

19-
Basis comes wrapped up as a framework and iOS and OS X. Simply add the project as a submodule, drag it to your project's file tree, and add it as a framework dependency for your build. When all is said and done, just
34+
Basis comes wrapped up as a framework and iOS and OS X. Simply add the project
35+
as a submodule, drag it to your project's file tree, and add it as a framework
36+
dependency for your build. When all is said and done, just
2037

2138
```
2239
import Basis
23-
```
40+
```
41+
42+
Introduction
43+
============
44+
45+
Because The Basis places emphasis on functions over structures, the majority of
46+
the functions in this repository are free and combinatorial. Programming with
47+
them then becomes a matter of selecting the proper combinators and compositional
48+
operators to achieve a desired type signature.
49+
50+
To take a famous example from Haskell:
51+
52+
```Swift
53+
/// Sorts a list by recursively partitioning its elements into sublists around a
54+
/// pivot element.
55+
func quickSort<T : Comparable>(l : [T]) -> [T] {
56+
switch destruct(l) {
57+
case .Empty:
58+
return []
59+
case let .Cons(x, xs):
60+
let lesser = xs.filter({ $0 < x })
61+
let greater = xs.filter({ $0 >= x })
62+
return quickSort(lesser) + [x] + quickSort(greater)
63+
}
64+
}
65+
```
66+
67+
Or perhaps a more convoluted example:
68+
69+
```Swift
70+
/// Lift any 1-ary function to a function over Maybes.
71+
func liftA<A, B>(f : A -> B) -> Maybe<A> -> Maybe<B> {
72+
return { a in Maybe.pure(f) <*> a }
73+
}
74+
75+
/// Lift any 2-ary function to a function over 2 Maybes.
76+
func liftA2<A, B, C>(f : A -> B -> C) -> Maybe<A> -> Maybe<B> -> Maybe<C> {
77+
return { a in { b in Maybe.pure(f) <*> a <*> b } }
78+
}
79+
80+
/// Lift any 3-ary function to a function over 3 Maybes.
81+
func liftA3<A, B, C, D>(f : A -> B -> C -> D) -> Maybe<A> -> Maybe<B> -> Maybe<C> -> Maybe <D> {
82+
return { a in { b in { c in Maybe.pure(f) <*> a <*> b <*> c } } }
83+
}
84+
```
85+
86+
With such an architecture in place, we can replace the classic `if-let` pattern
87+
for optionals with calls to liftA2:
88+
89+
```Swift
90+
let a = Maybe.just(6)
91+
let b = Maybe<Int>.nothing()
92+
let c = Maybe.just(5)
93+
94+
/// The result of adding 6 to Nothing is Nothing.
95+
let nothing = liftA2(curry(+))(a)(b)
96+
97+
/// The result of adding 5 and 6 is 11
98+
let something = liftA2(curry(+))(a)(c)
99+
100+
/// The result of packing 6, 5, and Nothing into a tuple is Nothing.
101+
let noTupleHere = liftA3(pack3)(a)(b)(c)
102+
```
103+
104+
We can also exploit the tools Swift has given us for laziness and use them to
105+
build up infinite data structures despite having only a finite amount of memory.
106+
107+
```Swift
108+
/// Returns a stream of every Natural Number. Because Streams a are built up
109+
/// iteratively only on demand, we needn't load every member of the at once,
110+
/// just one at a time as they are requested.
111+
///
112+
/// arr[0] == 0, arr[1] == 1, arr[2] == 2, ..., arr[n] == n
113+
let naturalNumbers = iterate({ 1 + $0 })(0)
114+
115+
/// Returns an stream consisting of only the items in a given list.
116+
///
117+
/// arr[0] == "You", arr[1] == "Say", arr[2] == "Goodbye", arr[4] == "You", ...
118+
let butISayHello = cycle(["You", "Say", "Goodbye"])
119+
```
120+
121+
Or even use laziness to help with control flow.
122+
123+
```Swift
124+
/// A version of the factorial function that, while appearing recursive,
125+
/// actually evaluates in a constant amount of stack space. As such it will
126+
/// never smash the stack no matter how large an input it is given.
127+
func noSmashFactorial(x : Double, _ acc : Double = 1.0) -> Trampoline<Double> {
128+
if x <= 1 {
129+
return now(acc)
130+
}
131+
return later(noSmashFac(x - 1, acc * x))
132+
}
133+
134+
/// The result of invoking this function is about 10^10^5.328. Obviously, such
135+
/// a number is completely unrepresentable in any bitwidth Swift gives us. The
136+
/// thing to notice is that we would have pushed 50,000 frames onto the stack.
137+
/// Instead we push just 1.
138+
let inf = noSmashFactorial(50000).run()
139+
```
140+
141+
We're no strangers to the Real World either. Swift is a profoundly imperative
142+
language at heart, but that doesn't mean we can't do something about it. Enter
143+
the IO Monad. Our IO Monad is the incarnation of an effect that has yet to
144+
happen.
145+
146+
```Swift
147+
/// An effect that, when executed, will pause for input from the terminal, then
148+
/// shout it back at you.
149+
let eff = interact(pack map({ $0.toUpper() }) unpack)
150+
/// ...
151+
/// Executes the effect with the current state of the world.
152+
eff.unsafePerformIO()
153+
```
154+
155+
System Requirements
156+
===================
157+
158+
The Basis supports OS X 10.9+ and iOS 7.0+
159+
160+
License
161+
=======
162+
163+
The Basis is released under the MIT license.
164+
165+
Further Reading
166+
===============
167+
168+
- [SML](http://en.wikipedia.org/wiki/Standard_ML)
169+
- [Haskell](http://haskell.org/)
170+
- [TTFP](https://www.cs.kent.ac.uk/people/staff/sjt/TTFP/)
171+

0 commit comments

Comments
 (0)