Either<L, R>:例外を使わない型付きエラー処理
例外をスローせずに成功と失敗を表すには、Eitherを使用します。
「Either<L, R>:例外を使わない型付きエラー処理」はCoddyKit上の無料Kotlin Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはKotlin Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Kotlin Academyコースには全4レッスンが含まれています。
ビジネスロジックに例外を使う問題点
例外は、予期しない失敗(nullポインター、I/Oエラーなど)のために設計されています。予期されるビジネス上の失敗(バリデーション失敗、「見つからない」など)を通知するために例外を使うと、制御フローが見えにくくなり、呼び出し箇所ごとにtry/catchが必要になり、関数シグネチャからエラーが分からなくなります。
Either<L, R>とは
Eitherは2つのケースを持つ直和型です。慣例として、Left(value: L)にはエラーを、Right(value: R)には成功した値を格納します。Eitherを返す関数では、失敗する可能性がシグネチャに明示されます。
ArrowのEither
プロジェクトにArrowを追加すると、Eitherと、その豊富な演算子エコシステムを利用できます。
// build.gradle.kts
implementation("io.arrow-kt:arrow-core:1.2.4")
// Usage
import arrow.core.Either
import arrow.core.left
import arrow.core.right関数からEitherを返す
成功時はvalue.right()を、失敗時はerror.left()を返します。呼び出し側では両方の分岐を処理する必要があります。
sealed class UserError { object NotFound : UserError(); data class InvalidEmail(val msg: String) : UserError() }
fun findUser(id: Long): Either<UserError, User> =
if (id <= 0) UserError.NotFound.left()
else User(id, "Alice").right()foldでEitherを処理する
fold(ifLeft, ifRight)を使用すると、1つの式で両方のケースを処理できます。
val result = findUser(1L)
val message = result.fold(
ifLeft = { error -> "Error: $error" },
ifRight = { user -> "Found: ${user.name}" }
)
println(message)mapでRightの値を変換する
map { }はLeftには触れずにRightの値を変換します。これによりEitherはファンクターとして機能し、変換を安全に連結できます。
val nameResult: Either<UserError, String> = findUser(1L).map { it.name }flatMapで処理を連結する
flatMap { }は、それ自体がEitherを返す計算を連結します。いずれかのステップがLeftを返すと、連結処理はそこで短絡し、後続のステップを実行せずにエラーが伝播します。
fun validateEmail(email: String): Either<UserError, String> =
if (email.contains("@")) email.right()
else UserError.InvalidEmail("bad format").left()
fun createUser(email: String): Either<UserError, User> =
validateEmail(email).flatMap { validEmail ->
User(1L, validEmail).right()
}Either.catchで例外をラップする
Either.catch { }はブロックを実行し、発生した例外をLeftとしてラップします。例外をスローするレガシーコードと、Eitherベースのドメインとの境界で使用します。
val result: Either<Throwable, User> = Either.catch {
userRepository.findOrThrow(id)
}getOrElseとorElseで復旧する
getOrElse { default }はRightの値を取り出し、Rightでなければデフォルト値を返します。orElse { alternativeEither }はLeftを別の計算結果に置き換えます。
val user: User = findUser(0L).getOrElse { User(-1L, "Guest") }
val user2: Either<UserError, User> = findUser(0L).orElse { User(99L, "Default").right() }whenによるパターンマッチング
sealedなEither風クラスに対してwhenを使用するか、is Either.Left / Either.Rightを使ってEither自体に対して使用すると、すべてのケースを網羅的に処理できます。
when (val r = findUser(1L)) {
is Either.Left -> println("Error: ${r.value}")
is Either.Right -> println("User: ${r.value.name}")
}サービスレイヤーでEitherを使う
リポジトリ関数とサービス関数からEitherを返します。KtorのルートレベルでHTTPレスポンスに変換することで、ビジネスロジックをフレームワークの関心事から分離できます。
get("/users/{id}") {
val id = call.parameters["id"]?.toLongOrNull() ?: return@get call.respond(HttpStatusCode.BadRequest)
userService.findById(id).fold(
ifLeft = { call.respond(HttpStatusCode.NotFound) },
ifRight = { call.respond(it) }
)
}理解度チェック
Either.Leftの値に対してflatMap { }を実行すると、どうなりますか。
振り返り:Either<L, R>
主なポイント:
Eitherによって、失敗時の処理が関数シグネチャに明示されますRight= 成功。Left= 失敗(慣例)map { }— 成功した値を変換します。flatMap { }— 失敗する可能性のある計算を連結しますfold(ifLeft, ifRight)— 1つの式で両方のケースを処理しますEither.catch { }— 例外をスローするコードを境界でラップします
よくある質問
「Either<L, R>:例外を使わない型付きエラー処理」レッスンは無料ですか?
はい。「Either<L, R>:例外を使わない型付きエラー処理」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Kotlin Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Kotlin Academyコースには全4レッスンが含まれています。
「Either<L, R>:例外を使わない型付きエラー処理」で何を学びますか?
例外をスローせずに成功と失敗を表すには、Eitherを使用します。 ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Kotlin Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのKotlin Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「Either<L, R>:例外を使わない型付きエラー処理」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このKotlin Academyレッスンでコードを書いて実行できますか?
はい。すべてのKotlin Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Either :例外を使わない型付きエラー処理
- Arrow Raise DSL:型付きエラーの合成
- OptionとNullable:それぞれを使う場面
- Arrowのコア型による関数型ドメインモデリング