 
 import Foundation
 
-// A model for a success or failure case.
-// This type precisely represents the domain of results of a function call that either returns a value of T or throws an error.
+/**
+ A model for a success or failure case.
 
-// Result<T> is used by Promise<T> to represent success or failure outside the normal flow of synchronous execution.
+ This type precisely represents the domain of results of a function call that either returns a value or throws an error.
+ 
+ Result is used by `Promise` to represent success or failure outside the normal flow of synchronous execution.
+ 
+ Result is a functor and a monad; you can map and flatMap.
 
-// Result is a functor and monad; you can map and flatMap.
-// map transforms success values into new success values but merely forwards errors.
-// flatMap also forwards errors, but transforms to a new Result, meaning it may produce a new failure.
-// tryMap transforms success values but can throw errors, which are caught and encoded as new failures.
+ - `map` transforms a success value into a new success value, but preserves errors.
+ - `flatMap` also preserves errors, but transforms a success value to a new Result, meaning it may produce a new failure.
+ - `tryMap` works like `flatMap`, but uses a transformation function that returns or throws.
+ */
+public enum Result<Value> {
 
-public enum Result<T> {
-
-    public typealias Value = T
-
+    /// A successful result wrapping a returned value.
     case success(Value)
+    /// A failed result wrapping a thrown error.
     case failure(Error)
 
-    // Create a Result by returning a value or throwing an error.
+    /**
+     Creates a result by immediately invoking a function that returns or throws.
+
+     - parameter create: A function whose returned value or thrown error becomes wrapped by the result.
+
+     The opposite operation is `value()`.
+     */
     public init(create: () throws -> Value) {
         do {
             let value = try create()


}

// From two Results, return one Result of their values or the first failure.
public func zip<A, B>(_ resultA: Result<A>, _ resultB: Result<B>) -> Result<(A, B)> {
    return resultA.tryMap { a in
        (a, try resultB.value())
    }
}

// From three Results, return one Result of their values or the first failure.
public func zip<A, B, C>(_ resultA: Result<A>, _ resultB: Result<B>, _ resultC: Result<C>) -> Result<(A, B, C)> {
    return zip(resultA, resultB).tryMap { a, b in
        (a, b, try resultC.value())
    }
}

// From four Results, return one Result of their values or the first failure.
public func zip<A, B, C, D>(_ resultA: Result<A>, _ resultB: Result<B>, _ resultC: Result<C>, _ resultD: Result<D>) -> Result<(A, B, C, D)> {
    return zip(resultA, resultB, resultC).tryMap { a, b, c in
        (a, b, c, try resultD.value())
    }
}

// From an array of Results, return one Result of an array of their values or the first failure.
public func zipArray<T>(_ results: [Result<T>]) -> Result<[T]> {
    return results.reduce(Result { [] }) { arrayResult, itemResult in
        arrayResult.tryMap { array in

        }
    }

    /**
     Returns or throws the wrapped value or error.
     
     - throws: The wrapped error, if the result is a failure.
     - returns: The wrapped value, if the result is a success.
     
     The opposite operation is `init(create:)`.
     */
    public func value() throws -> Value {
        switch self {
        case .success(let value):
