NonEmptyList[Scala with Cats]の説明

# 初めに
<b>`NonEmptyList`とは...値を１つ以上持っていることが保証されているデータ型です。後続処理で「Listが空だったら」という考慮をする必要がありません。</b>

Scala with Catsの`NonEmptyList`について[公式ドキュメント](https://typelevel.org/cats/datatypes/nel.html)を自分なりに翻訳して説明していきます！！
※ところどころ、分かりやすいように文を付け加えてます！

# モチベーション
`NonEmptyList`の2つの例から見ていきましょう！

## `Validated`および`Ior`での使用
`Validated`（[公式ドキュメント](https://typelevel.org/cats/datatypes/validated.html))や`Ior`（[公式ドキュメント](https://typelevel.org/cats/datatypes/ior.html))を見た場合、一般的なケースであれば、これらのデータ構造の1つで`NonEmptyList`が使用されているでしょう。

なぜかというと、エラー報告のときに都合がいいからです。名前から分かるように`NonEmptyList`は<b>少なくとも1つの要素を持つという特殊なデータ型</b>です。(よって、<b>後続処理で「Listが空だったら」という考慮をする必要がありません</b>。)
それ以外は通常の`List`のように動作します。`Validated`（および`Ior`）のようなsum type（値が同じであっても、各値が元のタイプのどれからのものであるかを追跡する複数のタイプの結合を表す型）の場合、エラー無しで`Invalid`を持つことは意味がありません。エラーが無いということは、それは`Valid`であるということを意味します！
`NonEmptyList`を使用することにより、次のようなことが型で明確に分かります。

`Invalid`の場合、少なくとも1つエラーがあります。

これだとより正確になり、後でエラーを報告するときにエラーのListが空である可能性を疑う必要がなくなります。

## より具体的な引数の要求によって`Option`を回避する
関数型プログラマーである私たちは当然、`List`などの有名な`head`メソッドのような例外をスローする可能性のある部分関数を避けます。

平均を計算する関数を例として取り上げましょう。

```Scala
def average(xs: List[Int]): Double = {
  xs.sum / xs.length.toDouble
}
```

0による除算は例外をスローするため、これは明らかに空のListにとって有効な定義ではないです。これを修正する1つの方法は、`Double`ではなく`Option`を返すことです。

```Scala
def average(xs: List[Int]): Option[Double] = if (xs.isEmpty) {
  None
} else {
  Some(xs.sum / xs.length.toDouble)
}
```

これだと機能しますし安全です。しかし、これは無効な入力を受け入れている問題を隠すだけです。
`Option`を使用することにより、空のListを処理するロジックで`average`関数を拡張しています。さらに、この関数の呼び出し元は毎回`Option`の処理をする必要があります。
例外を見落として失敗するよりはましですが、完璧には程遠いです。

代わりに表したいのは、`average`関数は空のListには全く意味が無いということです。ラッキーなことに、Catsでは`NonEmptyList`を定義しています！これは構造上、空にすることができないListを表しています。つまり、`NonEmptyList[A]`が与えられた場合、そこには<b>少なくとも1つの`A`がある</b>ことが分かります。

それが`average`関数にどう影響するか見てみましょう。

```Scala
import cats.data.NonEmptyList
def average(xs: NonEmptyList[Int]): Double = {
  xs.reduceLeft(_+_) / xs.length.toDouble
}
```

これにより、`average`関数はListが空であるかの検証がなくなり、Listの平均を計算するロジックに集中できます。これは、入力がシステムに入力されるプログラムの境界に入力の検証を移すという薦めとうまく結びついています。

# NonEmptyListの構造
`NonEmptyList`は次のように定義されています。

```Scala
final case class NonEmptyList[+A](head: A, tail: List[A]) {
  // Implementation elided
}
```

`NonEmptyList`の`head`は空ではありません。一方、`tail`は、`List`に要素を0個以上含めることができます。

# NonEmptyListの要素の定義
`NonEmptyList`の重要な特徴は、全体性です。`List`の場合、`head`と`tail`の両方が部分的であり、少なくとも1つの要素がある場合にのみ、明確に定義されます。

一方、`NonEmptyList`は、空の`NonEmptyList`を作成することは不可能であるため、`head`や`tail`などの操作が定義されていることを保証します。

# NonEmptyListの生成
`NonEmptyList`を作成するには、さまざまな方法があります。

## `one`の使用
引数が1つだけの`NonEmptyList`を作成する場合は、`NonEmptyList.one`を使用します。

```Scala
NonEmptyList.one(42)
// res0: NonEmptyList[Int] = NonEmptyList(42, List())
```

## `of`の使用
`NonEmptyList.of`の定義

```Scala
def of[A](head: A, tail: A*): NonEmptyList[A]
```

少なくとも1つの`A`とそれに続く`tail`の可変引数を持つ引数Listを受け入れます。次のように呼び出してください。

```Scala
NonEmptyList.of(1)
// res1: NonEmptyList[Int] = NonEmptyList(1, List())
NonEmptyList.of(1, 2)
// res2: NonEmptyList[Int] = NonEmptyList(1, List(2))
NonEmptyList.of(1, 2, 3, 4)
// res3: NonEmptyList[Int] = NonEmptyList(1, List(2, 3, 4))
```

接頭と最後の要素に通常の`List[A]`をとる`ofInitLast`もあります。

```Scala
NonEmptyList.ofInitLast(List(), 4)
// res4: NonEmptyList[Int] = NonEmptyList(4, List())
NonEmptyList.ofInitLast(List(1,2,3), 4)
// res5: NonEmptyList[Int] = NonEmptyList(1, List(2, 3, 4))
```

## `fromList`の使用
`Option[NonEmptyList[A]]`を返す`NonEmptyList.fromList`もあります。

```Scala
NonEmptyList.fromList(List())
// res6: Option[NonEmptyList[Nothing]] = None
NonEmptyList.fromList(List(1,2,3))
// res7: Option[NonEmptyList[Int]] = Some(NonEmptyList(1, List(2, 3)))
```

最後に大事なのがこちら。`List`の構文をimportすると`.toNel`があります。

```Scala
import cats.syntax.list._
List(1,2,3).toNel
// res8: Option[NonEmptyList[Int]] = Some(NonEmptyList(1, List(2, 3)))
```

## `fromFoldable`と`fromReducible`の使用
`NonEmptyList.fromFoldable`および`NonEmptyList.fromReducible`を使用できます。 2つの違いは、`fromReducible`は空でないデータ構造でのみ使用できるため、戻り値の型の`Option`を回避できることです。

ここでいくつかの例を示します。

```Scala
import cats.implicits._

NonEmptyList.fromFoldable(List())
// res9: Option[NonEmptyList[Nothing]] = None
NonEmptyList.fromFoldable(List(1,2,3))
// res10: Option[NonEmptyList[Int]] = Some(NonEmptyList(1, List(2, 3)))

NonEmptyList.fromFoldable(Vector(42))
// res11: Option[NonEmptyList[Int]] = Some(NonEmptyList(42, List()))
NonEmptyList.fromFoldable(Vector(42))
// res12: Option[NonEmptyList[Int]] = Some(NonEmptyList(42, List()))

// Everything that has a Foldable instance!
NonEmptyList.fromFoldable(Either.left[String, Int]("Error"))
// res13: Option[NonEmptyList[Int]] = None
NonEmptyList.fromFoldable(Either.right[String, Int](42))
// res14: Option[NonEmptyList[Int]] = Some(NonEmptyList(42, List()))

// Avoid the Option for things with a `Reducible` instance
import cats.data.NonEmptyVector
NonEmptyList.fromReducible(NonEmptyVector.of(1, 2, 3))
// res15: NonEmptyList[Int] = NonEmptyList(1, List(2, 3))
```

以上で[公式ドキュメント](https://typelevel.org/cats/datatypes/nel.html)よりScala with Catsの`NonEmptyList`について説明終わりです！

ありがとうございました！！🙇‍♂️