吾輩はCompound Typeである 〜 タプル型と関数型の正体を探る


![image](https://qiita-image-store.s3.amazonaws.com/0/34405/69ed447a-9580-b440-0a60-6fcccd4fc3b4.png)

----

![image](https://qiita-image-store.s3.amazonaws.com/0/34405/6156f84c-7bca-7699-70fc-9edb7fd1f831.png)

----

![Extensionの好循環 のコピー.png](https://qiita-image-store.s3.amazonaws.com/0/34405/12f56760-cd11-b3ef-e89f-248078773919.png)


----

![image](https://qiita-image-store.s3.amazonaws.com/0/34405/08a6b08b-318e-3692-1c22-cbc9d42b86e3.png)

----

## 関数型やタプル型にExtensionを書く方法は？

----

### Not Found

The requested way not found in this language.

----

![image](https://qiita-image-store.s3.amazonaws.com/0/34405/4d79479b-edbe-26d1-8486-9813ac97cd33.png)

----

# 型(Type)

----

# 型(Type)

- named type
- compound type

----

# Type > named type

----

# named type

= 固有の名前を与えて定義できる型

- class type
- struct type
- enum type
- protocol type

----

## だいたいの型は、named type

```swift
public struct Array<Element> :
 CollectionType, MutableCollectionType, _DestructorSafeContainer
```

```swift
public struct Dictionary<Key : Hashable, Value> :
 CollectionType, DictionaryLiteralConvertible
```

```swift
public enum Optional<Wrapped> :
 _Reflectable, NilLiteralConvertible
```

----

###名前がある＝extendできる

----

# Type > compound type

----

# compound type

 = 名前のない型

- tuple type
- function type

----

### 名前がない＝extensionも書けない

----

# Type > compound type > tuple type

----

## tuple type

括弧で囲まれた、
0個以上の型のカンマ区切りリスト

```swift
(Melon, String, Bool)
```

----

## tuple type

　
コロンで要素名をつけられる

```swift
(melon: Melon, farmName: String, isTasty: Bool)
```

----

```swift
let tuple = (
    melon: Melon(),
    farmName: "夕張",
    isTasty: true
)
```

<img width="1400" alt="スクリーンショット 2016-07-10 13.41.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/34405/8351ebc4-f2e4-b70d-0f2e-493b776c3a85.png">

----

ちなみに、型Tをひとつだけもつタプルは型Tと同じ扱いになります

```swift
// 1個の要素をもつタプルに、タプルでない型を代入可能
let p: ((Int)) = 1
// ※ 型は let p: ((Int)) タプル型だと認識されている

// タプルでない型に、1個の要素をもつタプルを代入可能
let r: String = (((("a"))))
// ※ 型は let r: String

// タプルの存在を意識せず比較も可能
let f: ((((((Int))))) -> (((((((((String))))))))))
    = { return $0 == p ? r : r }
// ※ 関数の型は書いたとおりに
// let f: ((((((Int))))) -> (((((((((String)))))))))) になっている
```

----

# Type > compound type > function type

----

## 突然ですがここでクイズです

```swift
() -> Void
```

Q. この関数型の、引数・戻り値は？
　

----

## 突然ですがここでクイズです

```swift
() -> Void
```

Q. この関数型の、引数・戻り値は？

A. 何も引数に取らず、何も返さない関数？

----

### 🙅

----

```swift
() -> Void
```

Q. この関数型の、引数・戻り値は？

### 正解:

**空タプル**を引数に取り、**空タプル**を返す関数

----

## function type

![image](https://qiita-image-store.s3.amazonaws.com/0/34405/c7397d83-2e24-d30d-b297-2087a3d96a55.png)

----

## function type

![image](https://qiita-image-store.s3.amazonaws.com/0/34405/c7397d83-2e24-d30d-b297-2087a3d96a55.png)

```swift
() -> Void
```


----

## function type

![image](https://qiita-image-store.s3.amazonaws.com/0/34405/c7397d83-2e24-d30d-b297-2087a3d96a55.png)

```swift
() -> Void
```

※ ![image](https://qiita-image-store.s3.amazonaws.com/0/34405/ad9ee433-bbbc-c815-4f0a-8394cbb97844.png)

----

## function type

![image](https://qiita-image-store.s3.amazonaws.com/0/34405/c7397d83-2e24-d30d-b297-2087a3d96a55.png)

```swift
() -> Void
```

つまり、

- parameter type: `()`
- return type: `()`

----

検証してみよう

```swift
func hoge() {}

let p = ()
let r = hoge(p)
print(r)

```

----

検証してみよう

```swift
func hoge() {}

let p = ()
let r = hoge(p) // ←空タプルを引数として渡せる
print(r) // ()   ←空タプルを戻り値として受けられる

```

----

そう考えると…

`(Int) -> Melon`
`([Melon]) -> Melon?`
`(melon: Melon, farmName: String, isTasty: Bool) -> Melon?`

関数の引数って、タプルに見えてきませんか？

----

### というか、実際タプルなんです。

----

```swift
func taste(melon: Melon, farmName: String, isTasty: Bool) {
    print(farmName + "の🍈は" + (isTasty ? "おいしい" : "まずい"))
}

let tuple = (melon: Melon(), farmName: "夕張", isTasty: true)

//実際Swift2ではこれで通ったりする
taste(tuple)
```

----

Swift3では関数の引数にタプルを渡すのはエラーになるけど、一段抽象化すると、通る。

```swift
func taste(melon: Melon, farmName: String, isTasty: Bool) {
    print(farmName + "の🍈は" + (isTasty ? "おいしい" : "まずい"))
}

let tuple = (melon: Melon(), farmName: "夕張", isTasty: true)

//taste(tuple)
// Error: passing 3 arguments to a callee as a single tuple value has been removed in Swift 3
// see also: https://github.com/apple/swift/blob/master/test/Misc/misc_diagnostics.swift#L136

func apply<P, R>(to function: (P) -> R, parameter: P) -> R {
    return function(parameter)
}

apply(to: taste, parameter: tuple)
```

----

function typeを
`parameter type -> return type` という
シンプルなcompound typeとして表現するために、
`tuple` というcompound typeが役に立っているようだ

----

# まとめ

compound typeを理解すると、型の世界がもっとよく理解できる!

----

### で、結局、何故compound typeに対してはExtensionが書けないのかって？

…。


----

### で、結局、何故compound typeに対してはExtensionが書けないのかって？

…。

…何故でしょうね？
何か分かる方いらっしゃったらお話しましょう！

----

## 参考

The Swift Programming Language (Swift 2.2): Types
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html