[Swift] Resultのために今すぐ書くべきExtension

### Result

Result はOptionalに似通った型です。

Optionalは値が存在しているかいないかを表現できる型ですが、Result は**値**あるいは**値がない理由**を表現できる型です。
このResultをもっと積極的に使おうというのが趣旨です。

対応Swiftのバージョン： Swift 5.1 です。5.0でも動きません。

なお、書いた人がメソッドチェーン原理主義者の模様。

#### ifSuccess / ifFailure

名前の通り成功した時あるいは失敗した時のみに実行される関数を設定します。

```swift
extension Result {
    @discardableResult
    func ifSuccess(_ f: (Success) -> Void)-> Self {
        if case let .success(v) = self { f(v) }
        return self
    }

    @discardableResult
    func ifFailure(_ f: (Failure) -> Void) -> Self {
        if case let .failure(e) = self { f(e) }
        return self
    }
}
````

Selfを返しているのはメソッドチェーンをうまく使うためです。
@discardableresultを付けることで戻り値を利用しなくても警告が出ないようにしています。

利用例

```swift
struct AError: Error {}

Reuslt<Int, AError>(success: 0)
    .ifSuccess { print("Success", $0) }
    .ifFailure { print("Failure", $0) }
// prints Success 0
```

#### zip

```swift
extension Result {
    func zip<T>(_ other: Result<T, Failure>) -> Result<(Success, T), Failure> {
        flatMap { v1 in other.map { v2 in (v1, v2) } }
    }
}
````

使用例

```swift

func getID() -> Result<String, AError> {
    .success("Identifier")
}
func getPassword() -> Result<String, AError> {
    .success("PASSWORD")
}
func authrize(id: String, password: String) -> Result<(), AError> {
    .success(())
}

getID()
    .zip(getPassword())
    .flatMap(authrize)
    .ifSuccess { _ in print("OK") }
    .ifFailure { _ in print("NG") }
```

必要に応じて`zip3`や`zip4`を用意するのも良いでしょう。

#### sequence

`[Reuslt<T, E>]`を`Result<[T], E>`に変換する。

```swift
extension Sequence {
    func sequence<T, E>() -> Result<[T], E> 
    where Element == Result<T, E> {
        Result<[T], Error> { try map { try $0.get() } }
            .mapError { $0 as! E }
    }
}
```

`mapError`内で force cast を行っていますが、`try map { try $0.get() }`この部分が投げるErrorは`E`ですので問題ありません。

使用例

```swift
extension Array where Element == Int {
    func maxOrThrow() throws -> Int {
        guard let v = self.max() else { throw AError() }
        return v
    }
}

[Result<Int, AError>.success(0), .success(2), .success(3)]
    .sequence()
    .flatMap { a in 
        Result<Int, Error> { try a.maxOrThrow() }
            .mapError { $0 as! AError }
    }
    .ifSuccess { print($0) }
    .ifFailure { print("Error", $0) }
// prints 3
```

#### traverse

`Array`の各要素に`Result<T, E>`を返す関数を適用して`Result<[T], E>`に変換する。

```swift
extension Sequence {
    func traverse<T, E>(_ f: (Element) -> Result<T, E>) -> Result<[T], E> {
        map(f).sequence()
    }
}
```

使用例

```swift
(0...4)
    .traverse { i in Result<String, Error> { String(i) } }
    .ifSuccess { print($0) }
// prints ["0", "1", "2", "3", "4"]
```

#### reduce

`Result<[Element], E>`の`[Element]`に`reduce`を適用します。
残念ながら`Failure`の型情報が消失します。 Typed Throwsが実装されるのを祈りましょう。

```swift
extension Result {
    func reduce<T, V>(_ initialResult: T, _ nextPartialResult: (T, V) throws -> T) -> Result<T, Error>
    where Success == Array<V> {
        mapError { $0 as Error }
            .flatMap { a in .init { try a.reduce(initialResult, nextPartialResult) } }
    }
}
```

使用例

```swift
(0...4)
    .traverse { i in Result<String, Error> { String(i) } }
    .reduce("", +)
    .ifSuccess { print($0) }
// prints 01234
```

### ご意見お待ちしております！

「それはだめだろ」や「こんなのもあるよ」などのご意見お待ちしております！