Generiske funktorer og mappere
Skriv map-funktioner, der er generiske over enhver container
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 -> 10Functor-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 bumpAllHvorfor 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ærermapoverKind<F, A>.- Array- og Option-instanser implementerer den for deres URI'er.
- Generisk kode som
bumpAllfungerer 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.
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
- HKT-problemet i TypeScript
- Definition af typekonstruktører
- Det lette HKT-mønster
- Generiske funktorer og mappere