0Pricing
Kotlin Academy · Lezione

DSL Raise di Arrow: composizione degli errori tipizzati

Utilizzi il contesto Raise di Arrow e raise() per comporre in modo chiaro flussi con più errori.

DSL Raise di Arrow: composizione degli errori tipizzati è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.

Il limite del concatenamento di Either

Concatenare Either con flatMap crea lambda profondamente annidate quando sono presenti più operazioni sequenziali. Il Raise DSL di Arrow (introdotto in Arrow 1.2) offre una sintassi più pulita, in stile coroutine, utilizzando i context receiver o le funzioni di estensione di Kotlin.

Che cos'è Raise<E>?

Raise è un contesto che può sollevare (interrompendo il flusso con) un errore di tipo E. Una funzione che può fallire chiama raise(error) per interrompere ed effettuare la propagazione dell'errore, in modo simile al lancio di un'eccezione ma senza usare eccezioni.

Il builder either { }

Il builder either { } crea un Either a partire da un blocco che ha un Raise nello scope. Al suo interno, invochi raise(error) in caso di errore oppure restituisca semplicemente un valore in caso di successo:

import arrow.core.raise.either
import arrow.core.raise.Raise

fun validateAge(age: Int): Either<String, Int> = either {
    if (age < 0) raise("Age cannot be negative")
    if (age > 150) raise("Age too large")
    age
}

bind() — estrarre Either all'interno di either{}

All'interno di un blocco either { }, chiami .bind() su qualsiasi valore Either per estrarlo. Se il valore è un Left, bind() esegue automaticamente il raise e interrompe il blocco:

fun createUser(name: String, age: Int): Either<String, User> = either {
    val validName = validateName(name).bind()  // raises if Left
    val validAge  = validateAge(age).bind()    // raises if Left
    User(validName, validAge)                  // only reached if both succeed
}

ensure() — controllo inline di una condizione

ensure(condition) { error } è una forma abbreviata di if (!condition) raise(error). Mantiene concisa la logica di validazione:

fun validateEmail(email: String): Either<String, String> = either {
    ensure(email.contains("@")) { "Email must contain @" }
    ensure(email.length <= 255) { "Email too long" }
    email
}

ensureNotNull() — controllo dei valori null con Raise

ensureNotNull(value) { error } estrae un valore nullable oppure esegue il raise se il valore è null:

fun findUser(id: Long, repo: UserRepo): Either<UserError, User> = either {
    ensureNotNull(repo.findById(id)) { UserError.NotFound(id) }
}

Raise con context receiver (Arrow 1.2+)

È possibile dichiarare direttamente funzioni che richiedono un contesto Raise, senza racchiuderle in either { }:

context(Raise<String>)
fun requirePositive(n: Int): Int {
    ensure(n > 0) { "Must be positive" }
    return n
}

// Called inside either { }
val result = either { requirePositive(-1) }  // Left("Must be positive")

Aggregazione degli errori con zipOrAccumulate

Per impostazione predefinita, Raise interrompe il flusso al primo errore. Utilizzi zipOrAccumulate() per eseguire più validazioni e raccogliere tutti gli errori in una NonEmptyList:

val result: Either<NonEmptyList<String>, User> = either {
    zipOrAccumulate(
        { validateName(name).bind() },
        { validateAge(age).bind() }
    ) { validName, validAge -> User(validName, validAge) }
}

recover { } — gestione di errori specifici

Utilizzi recover { error -> ... } all'interno di either { } per gestire un errore sollevato specifico e fornire un valore di fallback, riprendendo il calcolo:

val name: String = either {
    findUser(0L).bind().name
}.recover { error ->
    if (error == UserError.NotFound) "Guest" else raise(error)
}.getOrNull() ?: "Guest"

Raise e concatenamento di Either: quando usare ciascuno

Utilizzi either { }.bind() per flussi lineari con più passaggi sequenziali: il codice viene letto come codice imperativo, ma rimane puro. Utilizzi il concatenamento con flatMap per brevi composizioni di due passaggi o quando si integra con altre librerie funzionali.

Testare le funzioni basate su Raise

Esegua il test chiamando la funzione all'interno di either { } e verificando il risultato. I matcher Kotest shouldBeLeft() e shouldBeRight() di Arrow rendono concise le asserzioni:

import arrow.core.shouldBeLeft
import arrow.core.shouldBeRight

@Test
fun `negative age returns Left`() {
    validateAge(-1).shouldBeLeft()
}

@Test
fun `valid age returns Right`() {
    validateAge(25).shouldBeRight(25)
}

Verifica rapida

All'interno di un blocco either { }, che cosa accade chiamando .bind() su un valore Either.Left?

Riepilogo: Raise DSL di Arrow

Punti chiave:

  • either { } crea un Either a partire da un blocco con Raise nello scope
  • .bind() estrae il valore da Either e interrompe il flusso in caso di Left
  • ensure(condition) { error } e ensureNotNull(value) { error } per i controlli inline
  • zipOrAccumulate() raccoglie più errori invece di interrompere il flusso al primo
  • Il codice viene letto come codice imperativo, pur rimanendo puramente funzionale

Domande Frequenti

La lezione «DSL Raise di Arrow: composizione degli errori tipizzati» è gratuita?

Sì — il testo completo di «DSL Raise di Arrow: composizione degli errori tipizzati» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.

Cosa imparerò in «DSL Raise di Arrow: composizione degli errori tipizzati»?

Utilizzi il contesto Raise di Arrow e raise() per comporre in modo chiaro flussi con più errori. Eserciti Kotlin Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Kotlin Academy?

Non è richiesta alcuna esperienza precedente. Kotlin Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «DSL Raise di Arrow: composizione degli errori tipizzati»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Kotlin Academy?

Sì. Ogni lezione Kotlin Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Either : gestione tipizzata degli errori senza eccezioni
  2. DSL Raise di Arrow: composizione degli errori tipizzati
  3. Option e nullable: quando utilizzare ciascuno
  4. Modellazione funzionale del dominio con i tipi fondamentali di Arrow
← Torna a Kotlin Academy