Combineでよく見るSwiftのNever型とは

Never let me go — けして私を離さないで、僕たちはけしてと言うけれどその約束を守るのは難しい。
でも僕たちの愛する Swift では `Never` は絶対的な `Never` でその単純さが美しかった。

まぁそんなポエムはいいんですけど、iOS13から導入された Combine ではよく `Never` という型を見る。

```swift
@Published var x = 0
@Published var y = 0

var timesPublisher: AnyPublisher<Int, Never> {
    $x.combineLatest($y)
        .map(*)
        .eraseToAnyPublisher()
}
```

`AnyPublisher<Int, Never>` と失敗したときの型が `Never` になっている。これはけして失敗しないことを型で表現してる。

`Publisher` protocol の定義を見てみると publisher は失敗した場合の型を指定する必要がある。例え失敗しない場合でも型を指定する必要があるので失敗しないということを表す `Never` がここで必要になってくる。

```swift
public protocol Publisher {

    /// The kind of values published by this publisher.
    associatedtype Output

    /// The kind of errors this publisher might publish.
    ///
    /// Use `Never` if this `Publisher` does not publish errors.
    associatedtype Failure : Error

    /// This function is called to attach the specified `Subscriber` to this `Publisher` by `subscribe(_:)`
    ///
    /// - SeeAlso: `subscribe(_:)`
    /// - Parameters:
    ///     - subscriber: The subscriber to attach to this `Publisher`.
    ///                   once attached it can begin to receive values.
    func receive<S>(subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input
}
```

## Uninhabited Types

`Never` という型がどういうものなのか関数を作ってみていく。

![Screen Shot 2019-11-24 at 2.36.33 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536067/3c156316-60ee-5a87-c1bb-356f34910dc5.png)


型の宣言だけした関数を用意してみるとエラーで `Int` を返す関数は `Int` を返してないと言われるのに対して `Never` を返す関数のエラーは何やらいつものエラーと違うものになってる。

> Function with uninhabited return type 'Never' is missing call to another never-returning function on all paths

uninhabited return type 'Never' というよくわからない説明をされる。
どうやら `Never` というのは普通の型とは違うらしい。

ここで `Never` の定義を見てみる。

```swift
public enum Never {}
```

普通の enum の定義だがそこには `case` が一つもなかった。
enum は init を持たないので `case` がないということは値を作ることができないということになる。

このように値を作れない型のことを uninhabited type という。


しかし値を作れない型が何の役に立つんだと思うかもしれない。
プログラムを書いてると値を返さない関数(無限ループ、プログラムの終了)を書きたくなることがある。`Never` があればそのような関数の型を正しく表現することができるようになる。

でも、値を返さない関数の時は `Void` で定義するじゃんと普通思う。

そこで Swift での `Void` が何なのか定義をみてみる。

```swift
public typealias Void = ()
```

Swift での `Void` は空のタプルの別名として定義されている。
そして Swift で関数定義する時に戻り値の型を定義しなかったら常に戻り値の型は `Void` になる。

```swift
func log(_ message: String) {
    print("Message: \(message)")
}

let logger: (String) -> Void = log

logger("This is void function")
```

空のタプルは `()` という型であり `let unit = ()` として値を作ることができる。
このようにただ一つしか値がない型をユニット型という。なので `()` の型や値のことをユニットとよく呼ぶ。

つまり Swift での値を返さない関数と思っていた ` -> Void` な関数は実際にはユニットを返してるのと同じ関数になる。

```swift
func f() -> Void {}
func g() { return () }
```

`print()` のように値を返さないと思っている関数は実は値を返している。

```swift
let printResult: Void = print("This is void function")
print(printResult)                  // => ()
```


## NeverとVoidの関数の違い

値を返さない無限ループの関数を作ってみる。

```swift
func giveMeNever() -> Never {
    while true {}
}
```

この値を返さない関数を値を返す関数の中で呼んでみる。

```swift
func giveMeNever() -> Never {
    while true {}
}

func giveMeInt() -> Int {
    giveMeNever()
}
```

`giveMeInt()` は `Int` の値を返してないけどエラーなくコンパイルすることができる。

`giveMeNever()` の代わりに `Void` を返す関数を呼んでみる。

![Screen Shot 2019-11-24 at 7.54.45 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536067/30d6ea0a-5a0f-0684-d608-41c9f1b50fdb.png)

> Cannot convert return expression of type '()' to return type 'Int'

`()` は `Int` に変換できないとエラーになった。
Swift は強い型づけされた言語なので変換できないと言われる、なのに `-> Never` を `Int` を返すところで呼んでもエラーにならない。`Never` だけ特別扱いなのだろうか？まるで `Never` が `Int` として扱われてるみたいだ。他の型でもいいのだろうか？ `Double` は？ `String` は？

```swift
func giveMeDouble() -> Double {
    giveMeNever()
}

func giveMeString() -> String {
    giveMeNever()
}
```

エラーにならなかった。このコードは Swift では許可されたコードになる。
まるで `Never` は `Int` でもあるし `Double`, `String` でもあるようだ。

`Never` のように値を作ることができなくて、すべての型のサブ型のことを型理論ではボトム型という。

## ボトム型
ボトム、底、底があるならこの世にはその逆の上の世界があると人は夢をみる。
型の世界にもボトムがあるようにトップがある。

ボトム型が全ての型のサブ型ならトップ型はその逆の全てのサブ型はトップ型のサブ型であるとなる。

![Types.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536067/0f1338f3-78c4-0de4-9f10-f46c3c8dd586.png)

Swift には `Any` という型がある。
`Any` はあらゆる型の値を表すことができる型だ。例え関数でもだ。

```swift
func anyWeSayAnyType(_ x: Int) -> Any {
    switch x {
    case 4:
      return 12

    case 3:
      return 12.34

    case 2:
      return true

    case 1:
      return "This is String type but it's also Any"

    default:
      return { (x: Int, y: Int) in x * y }
    }
}
```

`Any` のようにあらゆる型の値を表せるのをトップ型という。
その逆のボトム型はあらゆる型のサブ型なので `Int` でも `Double` でも `String` としても扱える。


## ボトム型のようでボトムじゃない Never

> まるで `Never` は `Int` でもあるし `Double`, `String` でもあるようだ。

と前に言った。本当にそうなのだろうか？
コードで確かめてみよう。

![Screen Shot 2019-11-25 at 1.44.30 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536067/791eecd9-ec73-cca3-2adf-1fb683dd4319.png)

`Never` は定義した型に変換できないとエラーになる。
しかしクロージャで包んであげるとエラーにはならない。

```swift
func isNeverBottomType() {
    let x: Int = { giveMeNever() }()
    let flag: Bool = { giveMeNever() }()
    let text: String = { giveMeNever() }()
}
```

このように Swift 5.1 では `Never` は本物のボトム型ではない。
`Never` のような uninhabited type を関数の戻り値とする場合だけボトム型のような振る舞いをする。

一応 Swift の設計者は `Never` を Swift 3 で導入した時にボトム型にすることを提案はしていた。
[Never as a universal "bottom" subtype](https://github.com/apple/swift-evolution/blob/master/proposals/0102-noreturn-bottom-type.md#never-as-a-universal-bottom-subtype)


## Neverによって得た型の表現力
Swift では`fatalError()` という関数をよくみる。致命的なエラーだからプログラムを終了するという関数だ。

定義を見てみる。

```swift
public func fatalError(_ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line) -> Never
```

`Never` を返してる。
しかし `fatalError()` は Swift 3以前は定義が違った。大体こんな定義だった。

```swift
@noreturn func fatalError(_ message: () -> String = String(), file: StaticString = #file, line: UInt = #line)
```

`Never` の代わりに `@noreturn` という注釈がつけられている。これはコンパイラにこの関数は戻り値がないということを教えている。
基本的には `Never` が使われてる意図と同じだ。

しかし `@noreturn` にはいくつか問題点があった。
次のような使い方をしたらどうなるだろうか？

```swift
@noreturn func square(_ x: Int) -> Int { ... }
@noreturn func runApp() throws { ... }
```

値を返す関数やエラーを投げる関数に `@noreturn` をつけたらどうすればいいだろうか？
コンパイラは最初の値を返す場合はエラーにしたらいいだろう、でもエラーを投げる場合は許可すべきだろうか？許可はするけど値は返さないとすればいいだろうか？それとも値を返さないしエラーを投げることもないとすればいいだろうか？明らかな正解はない。
注釈による戻り値がないことを表すとこのように複雑性が生まれる。

Swift はこの問題を `Never` を導入することによって解決した。
`Never` という値を作れない型で値を返せないことを型として表現した。とても単純で美しい解決方法だ。


## おわりに

ここまで読んでくださってありがとうございます。

`Never` というとても小さく単純な型をみてきた。
小さく単純なものを定義することによってプログラミングでよくある問題を表現することができるのは美しいと思う。

Never return Never