TypeScript Academy · Lektion

Generiske funktorer og mappere

Skriv map-funktioner, der er generiske over enhver container

Lektion 4 af 413 trin

Generiske funktorer og mappere er en gratis TypeScript Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i TypeScript Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. TypeScript Academy-kurset indeholder 4 lektioner i alt.

En generisk funktor

Nu bruger vi kodningen til det, den er beregnet til: en generisk map, der fungerer på enhver registreret beholder. Functor-grænsefladen, der parametriseres med en URI, erklærer én metode.

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

Array-instansen

En instans implementerer map for én URI. Array-instansen udfører mapning med den indbyggede metode til arrays. Dens Kind<"Array", A> opløses til A[].

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

Brug af Array-instansen

Når du kalder map på Array-instansen, transformeres hvert element, samtidig med at array-beholdertypen bevares.

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

Option-typen

Definér en Option som en værdi eller null, og registrér den. Dens map anvender kun funktionen, når der findes en værdi; ellers viderefører den null.

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

Option-instansen

Option-instansen bevarer option-beholderen: En funktion anvendes på værdien, og en null forbliver null.

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

Brug af Option-instansen

Den samme map-form fungerer nu på en helt anden beholder. Værdier, der er til stede, transformeres, mens fraværende værdier forbliver uændrede.

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

Én abstraktion, mange beholdere

Det er gevinsten. arrayFunctor og optionFunctor deler den samme Functor-grænseflade. Kode, der er skrevet mod Functor<F>, fungerer for begge uden ændringer.

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

Kald af den generiske funktion

bumpAll ved ikke og er ligeglad med, hvilken beholder den modtager. Giv instansen og dataene videre; resultatet bevarer beholdertypen.

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

Functor-love

En korrekt funktor følger to love: Mapning med identitetsfunktionen ændrer intet, og mapning med to funktioner i rækkefølge svarer til mapning med deres sammensætning. Både Array- og Option-instanserne ovenfor opfylder disse love.

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

Tilføjelse af flere instanser

Fordi abstraktionen er åben, kan nye beholdere tilsluttes ved at registrere en URI og levere en instans. Et Tree, et Result eller en Task kan hver især mappes med den samme generiske kode.

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

Hvorfor det er vigtigt

Generiske funktorer er indgangen til funktionelle abstraktioner i TypeScript: applicativer, monader og traverseringer. Hver af dem er en grænseflade over Kind<F, A> med instanser pr. beholder. Du forstår nu den mekanik, der gør fp-ts og Effect mulige.

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>;
}

Hurtigt tjek

Test din forståelse af generiske funktorer.

Opsummering

Du har skrevet en beholdergenerisk map.

  • Functor<F> erklærer map over Kind<F, A>.
  • Array- og Option-instanser implementerer den for deres URI'er.
  • Generisk kode som bumpAll fungerer for enhver registreret beholder.
  • Funktorlovene holder instanser velfungerende, og mere avancerede abstraktioner bygger videre på dette.

Kursus 24 er det næste: opbygning af typesikre parsere.

Gratis at komme i gang

Lær TypeScript med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
101
Lektioner
352

Ofte stillede spørgsmål

Er lektionen “Generiske funktorer og mappere” gratis?

Ja — hele teksten til “Generiske funktorer og mappere” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af TypeScript Academy-kurset, skal du opgradere til CoddyKit PRO. TypeScript Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Generiske funktorer og mappere”?

Skriv map-funktioner, der er generiske over enhver container Du øver dig i TypeScript Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på TypeScript Academy?

Der kræves ingen tidligere erfaring. TypeScript Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.

Hvor lang tid tager lektionen “Generiske funktorer og mappere”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne TypeScript Academy-lektion?

Ja. Alle TypeScript Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. HKT-problemet i TypeScript
  2. Definition af typekonstruktører
  3. Det lette HKT-mønster
  4. Generiske funktorer og mappere
← Tilbage til TypeScript Academy