0Pricing
TypeScript Academy · Lezione

Functor e mapper generici

Scriva funzioni map generiche per qualsiasi container.

Functor e mapper generici è una lezione TypeScript Academy gratuita su CoddyKit. Questa è la lezione 4 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 TypeScript Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso TypeScript Academy include 4 lezioni in totale.

Un functor generico

Ora usiamo la codifica per il suo scopo: un map generico che funziona con qualsiasi contenitore registrato. L'interfaccia Functor, parametrizzata tramite un URI, dichiara un metodo.

interface Functor<F extends URIS> {
  readonly URI: F;
  map<A, B>(fa: Kind<F, A>, f: (a: A) => B): Kind<F, B>;
}

L'istanza di Array

Un'istanza implementa map per un singolo URI. L'istanza di Array esegue il mapping con il metodo integrato degli array. Il suo Kind<"Array", A> viene risolto in A[].

const arrayFunctor: Functor<"Array"> = {
  URI: "Array",
  map: (fa, f) => fa.map(f)
};

Usare l'istanza di Array

Chiamare map sull'istanza di Array trasforma ogni elemento preservando il tipo di contenitore array.

const doubled = arrayFunctor.map([1, 2, 3], n => n * 2);
// doubled: number[] -> [2, 4, 6]

Il tipo Option

Definisca il tipo Option come un valore oppure null e lo registri. Il suo map applica la funzione solo quando è presente un valore; altrimenti propaga null.

interface URItoKind<A> { Option: A | null }
type Option<A> = A | null;

L'istanza di Option

L'istanza di Option preserva il contenitore Option: una funzione viene applicata al valore e un null resta null.

const optionFunctor: Functor<"Option"> = {
  URI: "Option",
  map: (fa, f) => (fa === null ? null : f(fa))
};

Usare l'istanza di Option

La stessa struttura di map ora funziona su un contenitore completamente diverso. I valori presenti vengono trasformati; quelli assenti restano invariati.

const a = optionFunctor.map(5, n => n + 1);    // 6
const b = optionFunctor.map(null, n => n + 1); // null

Un'astrazione, molti contenitori

Questo è il vantaggio principale. arrayFunctor e optionFunctor condividono la stessa interfaccia Functor. Il codice scritto per Functor<F> funziona per entrambi senza modifiche.

function bumpAll<F extends URIS>(
  F: Functor<F>,
  fa: Kind<F, number>
): Kind<F, number> {
  return F.map(fa, n => n + 1);
}

Chiamare la funzione generica

bumpAll non sa né si preoccupa di quale contenitore riceva. Si passano l'istanza e i dati; il risultato preserva il tipo di contenitore.

const arr = bumpAll(arrayFunctor, [1, 2]); // number[] -> [2, 3]
const opt = bumpAll(optionFunctor, 9);     // number | null -> 10

Le leggi dei functor

Un functor corretto rispetta due leggi: applicare la funzione identità non modifica nulla e applicare due funzioni in sequenza equivale ad applicare la loro composizione. Entrambe le istanze, di Array e di Option, rispettano queste leggi.

// map(fa, x => x) === fa
// map(map(fa, f), g) === map(fa, x => g(f(x)))

Aggiungere altre istanze

Poiché l'astrazione è estensibile, è possibile aggiungere nuovi contenitori registrando un URI e fornendo un'istanza. Un Tree, un Result o un Task: ciascuno può diventare mappabile con lo stesso codice generico.

// Register URI, implement Functor<"Tree">,
// and bumpAll works on trees too - no edits to bumpAll

Perché è importante

I functor generici sono il punto d'ingresso alle astrazioni funzionali in TypeScript: applicative, monadi e traversali. Ognuna è un'interfaccia basata su Kind<F, A>, con istanze per ogni contenitore. Ora comprende il meccanismo che rende possibili fp-ts ed Effect.

interface Monad<F extends URIS> extends Functor<F> {
  of<A>(a: A): Kind<F, A>;
  chain<A, B>(fa: Kind<F, A>, f: (a: A) => Kind<F, B>): Kind<F, B>;
}

Verifica rapida

Verifichi la sua comprensione dei functor generici.

Riepilogo

Ha scritto un map generico per i contenitori.

  • Functor<F> dichiara map su Kind<F, A>.
  • Le istanze di Array e Option lo implementano per i rispettivi URI.
  • Il codice generico come bumpAll funziona con qualsiasi contenitore registrato.
  • Le leggi dei functor mantengono le istanze coerenti; su questa base si costruiscono astrazioni più ricche.

Il prossimo è il corso 24: costruire parser sicuri dal punto di vista dei tipi.

Domande Frequenti

La lezione «Functor e mapper generici» è gratuita?

Sì — il testo completo di «Functor e mapper generici» è 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 TypeScript Academy, passa a CoddyKit PRO. Il corso TypeScript Academy include 4 lezioni in totale.

Cosa imparerò in «Functor e mapper generici»?

Scriva funzioni map generiche per qualsiasi container. Eserciti TypeScript 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 TypeScript Academy?

Non è richiesta alcuna esperienza precedente. TypeScript 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 4 di 4.

Quanto tempo richiede la lezione «Functor e mapper generici»?

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 TypeScript Academy?

Sì. Ogni lezione TypeScript 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. Il problema HKT in TypeScript
  2. Definire costruttori di tipi
  3. Il pattern HKT leggero
  4. Functor e mapper generici
← Torna a TypeScript Academy