以前、so でみつけたこういうコード。
extension Array where Element: Collection {
func toD1() -> [Element.Element] {
return self.flatMap { $0 }
}
}
👉 【 Swift 】2次元配列と1次元配列の相互変換 🤔 
なんとなく「Collection」 の部分が気持ち悪かったのであれこれやってみます。
■ お題
2次元配列を平坦化します。
let data = [
["あ", "い", "う"],
["え", "お"]
]
print(data.flatMap { $0 })
// ["あ", "い", "う", "え", "お"]
print(Array(data.joined()))
// ["あ", "い", "う", "え", "お"]
これを extension 化しようとして、
extension Array {
var flattened: [String] {
flatMap { $0 }
}
}

Instance method 'flatMap' requires that 'Element' conform to 'Sequence'
とエラーがでるとこからスタートです。
■ やってみた
ドキュメントや先人の記事を読んでおきます。
👉 Element | Apple Developer Documentation 
👉 Array | Apple Developer Documentation 
👉 [Swift]Array型 #Swift - Qiita 
型や制約の記述を確認しながら進みます。
extension Array where Element == Array<String> {
var flattened: [String] {
// Array(joined()) // Cannot convert return expression of type 'Array<Array<String>>' to return type '[String]'
// joined().map { $0 } // OK
// Array<String>(joined()) // OK
// [Element.Element](joined()) // OK
// [String](joined()) // OK
flatMap { $0 } // OK
}
extension [[String]] where Element == [String] {
var flattened: [String] {
flatMap { $0 }
}
}
// ["あ", "い", "う", "え", "お"]
extension Array where Element == [String], Element.Element == String {
var flattened: [Element.Element] {
flatMap { $0 }
}
}
// ["あ", "い", "う", "え", "お"]
ここで、制約を先祖のプロトコルのみにします。
extension Array where Element: Collection {
var flattened: [Element.Element] {
flatMap { $0 }
}
}
// ["あ", "い", "う", "え", "お"]
揃えたほうが良さげです。
extension Collection where Element: Collection {
var flattened: [Element.Element] {
flatMap { $0 }
}
}
// ["あ", "い", "う", "え", "お"]
スッキリしました !
Sequence でもいけるんですね。
extension Sequence where Element: Sequence {
var flattened: [Element.Element] {
flatMap { $0 }
}
}
// ["あ", "い", "う", "え", "お"]
👉 誰もが知りたいSequenceとCollectionのすべて 
ちなみに、元の配列に nil を混ぜると、
let data = [
["あ", nil, "う"],
["え", "お"]
]
上手に処理してくれてますね!
// [Optional("あ"), nil, Optional("う"), Optional("え"), Optional("お")]
■ まとめ
プロトコルと型。
よく分かってませんが
なんだか深そうです。
そういえば、どこかに書いてました、
プロトコルを使用することによって得られる柔軟性と、特定の型のメソッドの作成の容易さのバランス
というようなフレーズ。
ありがとうございます。
どこか継承グラフみれるとことかあるのでしょうか ? 独自に書き出さずに。
👉 Dash for macOS - API Documentation Browser, Snippet Manager - Kapeli 
👉 realm/jazzy: Soulful docs for Swift & Objective-C 