Eitherの本質、使い方、動作原理

著者: IT Sectr 公開日: 2026-05-26 読了時間: 8 分

Eitherは、2つの可能なバリアントのいずれかの値を表す関数型です。Leftはエラー、Rightは成功を示します。例外とは異なり、Eitherは型レベルでエラーハンドリングを明示的にし、try-catchブロックを必要としません。Arrow, 2026によると、EitherはKotlinプロジェクトで副作用なしに失敗する可能性のある操作を構成するために広く使用されています。

重要なポイント

  • Eitherは、2つの相互排他的なバリアント(Left(エラー)とRight(成功))を表す代数的データ型です。
  • Leftは従来エラー情報を含み、Rightは正しい値を含みます。
  • 明示的な型付け — Eitherはコンパイル時に両方のバリアントを処理することを強制し、予期しない障害を排除します。
  • 合成 — Eitherはネストされたチェックなしで変換チェーンのためにmap、flatMap、foldをサポートします。
  • Resultとの違い — EitherはErrorやThrowableだけでなく、任意のエラー型を格納できます。

Eitherとは?

Eitherは関数型プログラミングから借用された代数的データ型で、2つの可能な型のうち正確に1つの値を表します。エラーハンドリングの文脈では、慣例としてLeft型(Left)が問題の説明を含み、Right型(Right)が成功結果を含みます。

Eitherの概念はHaskell言語と型カテゴリEither a bに由来し、aは左の値の型、bは右の値の型です。モバイル開発では、EitherはKotlin用のArrowライブラリとSwiftの関数型アプローチによって広まりました。

例外に対するEitherの主な利点は隠れた実行パスがないことです。Eitherを返す関数は、そのシグネチャで失敗する可能性があることを明示的に宣言します。コンパイラは両方のバリアントが処理されていることを確認します。

例外をスローするのとは異なり、Eitherはデータフローの透過性を維持します。Eitherを返す関数の呼び出しは、呼び出し側でtry-catchを必要としません — pattern-matchingまたはfoldで十分です。これは、各データソースがEitherを返し、mapとflatMapを使用して変換チェーンが構築されるリアクティブアプローチのアーキテクチャで特に重要です。

Eitherの仕組み:LeftとRightの構造

EitherはLeftRightの2つのサブタイプで構成されます。Eitherインスタンスは常にそのうちの1つだけです。Kotlinでの典型的なシグネチャはEither<E, A>で、Eはエラー型、Aは成功値の型です。

Left型:エラーコンテナ

Leftは失敗のケースを表します。例外とは異なり、Leftは実行フローを中断しません — 処理が必要な値を返すだけです。エラー型は何でもかまいません:StringInt、カスタムのsealed class、またはドメインモデルです。

Right型:成功コンテナ

Rightは操作の正しい結果を含みます。名前が示すように、慣例によりRightは成功を意味します。mapやflatMapなどの変換はRightに適用され、各ステップをチェックすることなく計算チェーンを可能にします。

flatMapによるEitherの合成

flatMapはEither合成の主要なメカニズムです。現在の値がRightの場合、flatMapは渡された関数を適用して新しいEitherを返します。Leftの場合、flatMapは変換をスキップしてエラーを伝播します。この動作はショートサーキット評価と呼ばれます。

flatMapに加えて、EitherはmapLeft(エラー変換用)、fold(両方のバリアントを1箇所で処理するため)、getOrElse(デフォルト値で値を抽出するため)をサポートします。これらの関数は、単純な抽出からKotlinコルーチンやSwift Combineでの非同期呼び出しを含む複雑な合成まで、すべてのシナリオをカバーします。

kotlin
fun parseInt(input: String): Either<String, Int> =
    input.toIntOrNull()?.let { Right(it) }
    ?: Left("変換に失敗しました: $input")

fun divide(a: Int, b: Int): Either<String, Int> =
    if (b == 0) Left("ゼロによる除算")
    else Right(a / b)

val result = parseInt("10")
    .flatMap { divide(it, 2) }

KotlinでのEither:実践的な応用

Kotlinエコシステムでは、EitherはArrowライブラリで実装されています。Kotlin標準ライブラリはResultを提供しますが、Eitherはより柔軟です:任意のエラー型、flatMapによる合成、関数型パターンのサポートを備えています。

ArrowライブラリとEither

ArrowはKotlin用の関数型ライブラリで、Either、Option、Validatedなどの型を追加します。Arrow.Eitherは2つのサブクラスを持つsealed classです:ArrowCore.LeftArrowCore.Right。ライブラリは便利な拡張も提供します:.getOrElse().fold().mapLeft()

例:ネットワークリクエストでのEither

実際のシナリオを考えてみましょう — ネットワークなし、サーバーエラー、不正な応答などのエラーが発生する可能性のあるAndroidアプリでのネットワークリクエストです。Eitherを使用すると、すべてのバリアントを1つの戻り値の型にまとめることができます。

kotlin
sealed class NetworkError {
    data class NoConnection(val message: String): NetworkError()
    data class ServerError(val code: Int): NetworkError()
    data class ParseError(val detail: String): NetworkError()
}

suspend fun fetchUser(id: String): Either<NetworkError, User> {
    return try {
        val response = api.getUser(id)
        if (response.isSuccessful) {
            Right(response.body()!!)
        } else {
            Left(NetworkError.ServerError(response.code()))
        }
    } catch (e: IOException) {
        Left(NetworkError.NoConnection(e.message ?: ""))
    }
}

SwiftでのEither:標準のResultとの違い

Swiftではバージョン5.0以降、組み込みのResult型が利用可能で、概念的にはEitherに似ていますが制限があります:エラーはErrorプロトコルに準拠する必要があり、成功値は1つの型である必要があります。SwiftでのEitherは、2つのジェネリックパラメータを持つenumを使用して実装されます。

標準のResult vs. Either

Result<Success, Failure>はSwiftの組み込み型で、Failure: Errorです。Eitherはエラー型に制約を課さないため、String、カスタム構造体、ネストされたenumによる複数のエラー型を格納できます。

swift
enum Either<E, A> {
    case left(E)
    case right(A)

    func map<B>(_ transform: (A) -> B) -> Either<E, B> {
        switch self {
        case .left(let e): return .left(e)
        case .right(let a): return .right(transform(a))
        }
    }
}

let result: Either<String, Int> = .right(42)
let mapped = result.map { $0 * 2 }

モバイルアプリでEitherを使用するタイミング

Eitherは、例外なしで明示的かつ型安全なエラーハンドリングが必要なシナリオに最適です。KotlinとSwiftでのモバイル開発における主な使用例を考えてみましょう。

  • ネットワークリクエスト — 各リクエストは接続エラー、サーバーエラー、または解析エラーを返す可能性があります。Eitherはすべてのバリアントを1つの型にまとめます。
  • フォーム検証 — カスタムエラー型を持つEitherは、入力フィールドの検証結果(無効なメールやパスワード)を便利に表現します。
  • データリポジトリ — Eitherは異なるソース(キャッシュ、DB、ネットワーク)からの結果を統一されたエラー型で結合できます。
  • コマンドインタプリタ — アプリがユーザー入力やコマンドを解析する場合、Eitherはエラーを報告する型安全な方法を提供します。

副作用のない単純な操作にはEitherを使用しないでください — 通常の戻り値の方が信頼性が高く読みやすいです。また、失敗が例外的な状況であり予期されるシナリオでない場合、Eitherは過剰です。

EitherはKotlinのコルーチンでの作業にも効果的です。Eitherを返す関数は、スレッドをブロックせずにfoldまたはmapLeftによるエラーハンドリングとともにコルーチン内で呼び出すことができます。これは、各リポジトリがEitherを返し、ViewModelが結果をUiStateに変換するMVVMアーキテクチャのAndroidアプリで特に便利です。

Eitherを使用する際の一般的な間違い

Eitherに初めて触れる開発者は、よく似たような間違いを犯します。最も一般的なものとその回避方法を見てみましょう。

  • Leftの無視 — エラーの原因を分析せずにデフォルト値で.getOrElse()を呼び出すと、Eitherを使用する意味がなくなります。エラーを明示的に処理してください。
  • グローバルエラー型 — プロジェクト内のすべてのEitherに共通の型としてStringやExceptionを使用すると、型安全性が低下します。ドメインのsealed classを作成してください。
  • ネストされたEither — Rightの中のEither(Either<E, Either<E, A>>)は可読性を低下させます。平坦化にはflatMapを使用してください。
  • 例外との混在 — 関数がEitherを返すが内部で例外をスローする場合、これは明示的なエラーハンドリングの考えに矛盾します。

よくある質問

EitherとOptionalの違いは?

Optionalは値の有無(Some/None)を表しますが、欠如の理由は伝えません。Eitherはエラー用の左と成功用の右の2つの具体的な型を提供し、障害のコンテキストを伝達できます。

JavaでEitherは使えますか?

Javaには組み込みのEitherはありませんが、Vavrやfunctionaljavaライブラリが実装を提供しています。Android開発では、VavrのEitherがラムダを使用した関数型スタイルの一般的な代替手段です。

Eitherの代わりにsealed classを使うべきタイミングは?

KotlinのSealed classは、3つ以上のバリアントがある場合や構造が異なる場合に便利です。2値の結果(エラー/成功)には、Eitherの方がコンパクトで、すぐに使える関数型コンビネータを提供します。

Eitherはマルチスレッドをサポートしますか?

Eitherは不変であり、デフォルトでスレッドセーフです。Kotlinのコルーチンでは、Eitherは完全に組み合わせ可能です:flatMapはコルーチンスコープ内で機能し、エラーハンドリングにロックは必要ありません。

プロジェクトのすべての関数にEitherを使うべきですか?

いいえ。Eitherは予期される失敗(ネットワーク、検証、ビジネスロジック)のある操作に適しています。副作用のない単純なゲッターや計算には、通常の型の方が読みやすく、不必要な複雑さを追加しません。

まとめ

  • Eitherは2つのバリアント(Left(エラー)とRight(成功))を表す関数型で、型レベルでエラーハンドリングを明示的にします。
  • Leftは標準のResultとは異なり、Stringからドメインのsealed classまで任意のエラー型を保持できます。
  • flatMapはネストされたチェックなしでEitherの合成を可能にします:エラーは自動的にチェーン全体に伝播します。
  • ArrowはKotlin用の主要なEitherライブラリで、組み込みのコルーチンサポートと拡張を備えています。
  • Swiftは組み込みのResultを使用しますが、Eitherは完全な柔軟性のために2つのジェネリックパラメータを持つenumで実装できます。
  • Eitherはネットワークリクエスト、フォーム検証、リポジトリ — 予期されるエラーが発生するシナリオに使用します。
  • グローバルエラー型、Leftの無視、ネストされたEitherは避けてください — これらは型安全性の利点を低下させます。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください