Typ křižovatky - Intersection type
v teorie typů, an typ křižovatky lze přiřadit hodnotám, kterým lze přiřadit oba typy a typ . Tuto hodnotu lze zadat jako typ křižovatky v systém typu křižovatka.[1]Obecně platí, že pokud se rozsahy hodnot dvou typů překrývají, pak hodnota patřící k průsečík ze dvou rozsahů lze přiřadit typ křižovatky těchto dvou typů. Takovou hodnotu lze bezpečně předat jako argument očekávaným funkcím buď ze dvou typů. Například v Jáva třída Booleovský
implementuje oba Serializovatelné
a Srovnatelný
rozhraní. Proto objekt typu Booleovský
lze bezpečně předat funkcím očekávajícím argument typu Serializovatelné
a na funkce očekávající argument typu Srovnatelný
.
Křižovatkové typy jsou složené datové typy. Podobný typy produktů, slouží k přiřazení několika typů k objektu. Typy produktů jsou však přiřazeny n-tice, takže každému prvku n-tice je přiřazena konkrétní komponenta typu produktu. Pro srovnání, podkladové objekty typů průniků nemusí být nutně složené. Omezená forma typů křižovatek je typy upřesnění.
K popisu jsou užitečné typy křižovatek přetížené funkce.[2] Například pokud číslo => číslo
je typ funkce, která bere číslo jako argument a vrací číslo, a tětiva => tětiva
je typ funkce, která vezme řetězec jako argument a vrací řetězec, potom lze průnik těchto dvou typů použít k popisu (přetížených) funkcí, které dělají jeden nebo druhý, na základě toho, jaký typ vstupu jsou uvedeny.
Současné programovací jazyky, včetně Cejlon, Průtok, Jáva, Scala, Strojopis, a Whiley (vidět srovnání jazyků s typy průniků ), použijte typy křižovatek ke kombinování specifikací rozhraní a k vyjádření ad hoc polymorfismus. Doplňování parametrický polymorfismus, lze použít typy křižovatek, aby se zabránilo znečištění hierarchie tříd z průřezové obavy a snížit standardní kód, jak je uvedeno v Příklad strojopisu níže.
The teoretický typ studium typů křižovatek se označuje jako disciplína typu křižovatka.[3]Je pozoruhodné, že ukončení programu lze přesně charakterizovat pomocí typů křižovatek.[4]
Příklad strojopisu
Strojopis podporuje typy křižovatek,[5] zlepšení expresivity systému typů a zmenšení potenciální velikosti hierarchie tříd, demonstrováno následovně.
Následující programový kód definuje třídy Kuře
, Kráva
, a RandomNumberGenerator
že každý má svoji metodu vyrobit
vrácení objektu libovolného typu Vejce
, Mléko
nebo číslo
Navíc funkce jíst vejce
a pít mléko
vyžadují argumenty typu Vejce
a Mléko
, resp.
třída Vejce { soukromé druh: "Vejce" }třída Mléko { soukromé druh: "Mléko" }// produkuje vejcetřída Kuře { vyrobit() { vrátit se Nový Vejce(); } }// produkuje mlékotřída Kráva { vyrobit() { vrátit se Nový Mléko(); } }// vytvoří náhodné číslotřída RandomNumberGenerator { vyrobit() { vrátit se Matematika.náhodný(); } }// vyžaduje vejcefunkce jíst vejce(vejce: Vejce) { vrátit se „Snědl jsem vejce.“;}// vyžaduje mlékofunkce pít mléko(mléko: Mléko) { vrátit se „Vypil jsem mléko.“;}
Následující programový kód definuje ad hoc polymorfní funkce animalToFood
který vyvolá členskou funkci vyrobit
daného objektu zvíře
.Funkce animalToFood
má dva anotace typu, jmenovitě ((_: Kuře) => Vejce)
a ((_: Kráva) => Mléko)
, připojeno pomocí konstruktoru typu křižovatky &
Konkrétně animalToFood
při použití na argument typu Kuře
vrací objekt typu typu Vejce
, a při použití na argument typu Kráva
vrací objekt typu typu Mléko
.Ideálně, animalToFood
by nemělo být použitelné na žádný objekt, který má (možná náhodou) a vyrobit
metoda.
// dané kuře, produkuje vejce; vzhledem k tomu, kráva, produkuje mlékonechat animalToFood: ((_: Kuře) => Vejce) & ((_: Kráva) => Mléko) = funkce (zvíře: žádný) { vrátit se zvíře.vyrobit(); };
Nakonec ukazuje následující programový kód typ bezpečný použití výše uvedených definic.
1 var kuře = Nový Kuře(); 2 var kráva = Nový Kráva(); 3 var randomNumberGenerator = Nový RandomNumberGenerator(); 4 5 řídicí panel.log(kuře.vyrobit()); // Vejce {} 6 řídicí panel.log(kráva.vyrobit()); // Mléko {} 7 řídicí panel.log(randomNumberGenerator.vyrobit()); //0.2626353555444987 8 9 řídicí panel.log(animalToFood(kuře)); // Vejce {}10 řídicí panel.log(animalToFood(kráva)); // Mléko {}11 //console.log(animalToFood(randomNumberGenerator)); // ERROR: Argument typu 'RandomNumberGenerator' nelze přiřadit parametru typu 'Cow'12 13 řídicí panel.log(jíst vejce(animalToFood(kuře))); // Snědl jsem vejce.14 //console.log(eatEgg(animalToFood(cow))); // ERROR: Argument typu „Milk“ nelze přiřadit parametru typu „Egg“15 řídicí panel.log(pít mléko(animalToFood(kráva))); // Vypil jsem mléko.16 //console.log(drinkMilk(animalToFood(chicken))); // ERROR: Argument typu 'Egg' nelze přiřadit parametru typu 'Milk'
Výše uvedený programový kód má následující vlastnosti:
- Řádky 1–3 vytvářejí objekty
kuře
,kráva
, arandomNumberGenerator
jejich příslušného typu. - Řádky 5–7 vytisknou pro dříve vytvořené objekty příslušné výsledky (poskytované jako komentáře) při vyvolání
vyrobit
. - Řádek 9 (resp. 10) ukazuje typově bezpečné použití metody
animalToFood
aplikován nakuře
(resp.kráva
). - Řádek 11, pokud bude zrušen, by měl za následek chybu typu v době kompilace. Ačkoliv implementace z
animalToFood
mohl vyvolatvyrobit
metodarandomNumberGenerator
, anotace typu zanimalToFood
zakazuje to. To je v souladu se zamýšleným významemanimalToFood
. - Řádek 13 (resp. 15) ukazuje, že přihláška
animalToFood
nakuře
(resp.kráva
) má za následek objekt typuVejce
(resp.Mléko
). - Řádek 14 (resp. 16) ukazuje, že přihláška
animalToFood
nakráva
(resp.kuře
) nemá za následek objekt typuVejce
(resp.Mléko
). Pokud by tedy nebyl zadán komentář, řádek 14 (resp. 16) by vedl k chybě typu v době kompilace.
Srovnání s dědictvím
Výše uvedený minimalistický příklad lze realizovat pomocí dědictví, například odvozením tříd Kuře
a Kráva
ze základní třídy Zvíře
Ve větším prostředí by to však mohlo být nevýhodné. Zavádění nových tříd do hierarchie tříd nemusí být nutně odůvodněné. průřezové obavy, nebo možná zcela nemožné, například při použití externí knihovny. Je možné si představit, že výše uvedený příklad lze rozšířit o následující třídy:
- třída
Kůň
to nemávyrobit
metoda; - třída
Ovce
který mávyrobit
metoda se vracíVlna
; - třída
Prase
který mávyrobit
metoda, kterou lze použít pouze jednou, vrací seMaso
.
To může vyžadovat další třídy (nebo rozhraní) určující, zda je k dispozici metoda produkce, zda metoda produkce vrací jídlo a zda lze metodu produkce opakovaně používat. Celkově to může znečišťovat hierarchii tříd.
Srovnání s kachním psaním
Výše uvedený minimalistický příklad to již ukazuje kachní psaní je méně vhodný k realizaci daného scénáře. Zatímco třída RandomNumberGenerator
obsahuje a vyrobit
metoda, objekt randomNumberGenerator
by neměl být platným argumentem pro animalToFood
Výše uvedený příklad lze realizovat pomocí kachního psaní, například zavedením nového pole argumentForAnimalToFood
do tříd Kuře
a Kráva
znamenat, že objekty odpovídajícího typu jsou platné argumenty pro animalToFood
To by však nejen nezvýšilo velikost příslušných tříd (zejména se zavedením více podobných metod jako animalToFood
), ale jde rovněž o nelokální přístup animalToFood
.
Srovnání s přetížením funkce
Výše uvedený příklad lze realizovat pomocí přetížení funkce, například implementací dvou metod animalToFood(zvíře: Kuře): Vejce
a animalToFood(zvíře: Kráva): Mléko
.V TypeScript je takové řešení téměř totožné s poskytnutým příkladem. Jiné programovací jazyky, jako např Jáva, vyžadují odlišné implementace přetížené metody. To může vést k jedné duplikace kódu nebo standardní kód.
Srovnání se vzorem návštěvníků
Výše uvedený příklad lze realizovat pomocí vzor návštěvníka.Vyžadovalo by to, aby každá třída zvířat implementovala akceptovat
metoda přijímání objektu implementujícího rozhraní Zvířecí návštěvník
(přidání nelokálního standardní kód ).Funkce animalToFood
bude realizováno jako návštěva
způsob implementace Zvířecí návštěvník
Bohužel spojení mezi typem vstupu (Kuře
nebo Kráva
) a typ výsledku (Vejce
nebo Mléko
) by bylo obtížné představit.
Omezení
Na jedné straně typy křižovatek umět slouží k lokální anotaci různých typů k funkci bez zavedení nových tříd (nebo rozhraní) do hierarchie tříd. na druhou stranu, tento přístup vyžaduje všechny možné typy argumentů a typy výsledků, které mají být výslovně specifikovány.Pokud lze chování funkce přesně určit pomocí jednotného rozhraní, parametrický polymorfismus nebo kachní psaní, pak je podrobná povaha typů křižovatek nepříznivá. Proto by typy průniků měly být považovány za doplňkové ke stávajícím metodám specifikace.
Závislý typ křižovatky
A závislý typ křižovatky, označeno , je závislý typ ve kterém je typ může záviset na pojmu proměnná .[6]Zejména pokud je termín má závislý typ křižovatky , pak termín má oba typ a typ , kde je typ, který je výsledkem nahrazení všech výskytů proměnné výrazu v termínem .
Příklad Scala
Scala podporuje deklarace typu [7] jako členové objektu. To umožňuje, aby typ člena objektu závisel na hodnotě jiného člena, který se nazývá a typ závislý na cestě.[8]Například následující text programu definuje vlastnost Scala Svědek
, které lze použít k implementaci singletonový vzor.[9]
vlastnost Svědek { typ T val hodnota: T {}}
Výše uvedená vlastnost Svědek
prohlašuje člena T
, kterému lze přiřadit a typ jako jeho hodnota a člen hodnota
, kterému lze přiřadit hodnotu typu T
Následující text programu definuje objekt booleovský svědek
jako instance výše uvedené vlastnosti Svědek
.Objekt booleovský svědek
definuje typ T
tak jako Booleovský
a hodnota hodnota
tak jako skutečný
Například provádění Systém.ven.tisk(booleovský svědek.hodnota)
tiskne skutečný
na konzole.
objekt booleovský svědek rozšiřuje Svědek { typ T = Booleovský val hodnota = skutečný}
Nechat být typem (konkrétně a typ záznamu ) objektů majících člena typu .Ve výše uvedeném příkladu objekt booleovský svědek
lze přiřadit závislý typ křižovatky Odůvodnění je následující. Objekt booleovský svědek
má člena T
kterému je přiřazen typ Booleovský
jako jeho hodnota Booleovský
je typ, objekt booleovský svědek
má typ .Dále objekt booleovský svědek
má člena hodnota
kterému je přiřazena hodnota skutečný
typu Booleovský
Protože hodnota booleovský svědek.T
je Booleovský
, objekt booleovský svědek
má typ Celkově objekt booleovský svědek
má typ křižovatky .Proto, prezentující self-reference jako závislost, objekt booleovský svědek
má závislý typ křižovatky .
Alternativně lze výše uvedený minimalistický příklad popsat pomocí závislé typy záznamů.[10]Ve srovnání se závislými typy průniků představují závislé typy záznamů striktně specializovanější teoretický koncept typu.[6]
Křižovatka rodiny typů
An průnik typové rodiny, označeno , je závislý typ ve kterém je typ může záviset na pojmu proměnná .[6]Zejména pokud je termín má typ , pak pro každý období typu , termín má typ .Tento pojem se také nazývá implicitní Typ pí,[11] s ohledem na tento argument není veden na úrovni období.
Porovnání jazyků s typy průniků
Jazyk | Aktivně vyvinut | Paradigma | Postavení | Funkce |
---|---|---|---|---|
C# | Ano[12] | Probíhá diskuse[13] | ? | |
Cejlon | Ano[14] | Podporováno[15] |
| |
F# | Ano[16] | Probíhá diskuse[17] | ? | |
Tok | Ano[18] | Podporováno[19] |
| |
Forsythe | Ne | Podporováno[20] |
| |
Jáva | Ano[21] | Podporováno[22] |
| |
Scala | Ano[23] | Podporováno[24][25] |
| |
Strojopis | Ano[26] | Podporováno[5] |
| |
Whiley | Ano[27] | Podporováno[28] | ? |
Reference
- ^ Barendregt, Henk; Coppo, Mario; Dezani-Ciancaglini, Mariangiola (1983). Msgstr "Model filtru lambda a úplnost přiřazení typu". Journal of Symbolic Logic. 48 (4): 931–940. doi:10.2307/2273659. JSTOR 2273659.
- ^ Palsberg, Jens (2012). "Přetížení je NP-Complete". Logická a programová sémantika. Přednášky z informatiky. 7230. 204–218. doi:10.1007/978-3-642-29485-3_13. ISBN 978-3-642-29484-6.
- ^ Henk Barendregt; Wil Dekkers; Richard Statman (20. června 2013). Lambda kalkul s typy. Cambridge University Press. str. 1–. ISBN 978-0-521-76614-2.
- ^ Ghilezan, Silvia (1996). „Silná normalizace a typovatelnost s typy křižovatek“. Deník Notre Dame formální logiky. 37 (1): 44–52. doi:10.1305 / ndjfl / 1040067315.
- ^ A b "Typy křižovatek v TypeScript". Citováno 2019-08-01.
- ^ A b C Kopylov, Alexej (2003). "Závislá křižovatka: Nový způsob definování záznamů v teorii typů". 18. IEEE Symposium on Logic in Computer Science. LICS 2003. IEEE Computer Society. str. 86–95. CiteSeerX 10.1.1.89.4223. doi:10.1109 / LICS.2003.1210048.
- ^ "Zadejte prohlášení ve Scale". Citováno 2019-08-15.
- ^ Amin, Nada; Grütter, Samuel; Oderský, Martin; Rompf, Tiark; Stucki, Sandro (2016). "Podstata závislých typů objektů". Seznam úspěchů, které mohou změnit svět - Eseje věnované Philipu Wadlerovi u příležitosti jeho 60. narozenin. Přednášky z informatiky. 9600. Springer. 249–272. doi:10.1007/978-3-319-30936-1_14.
- ^ „Singletony v beztvaré knihovně Scala“. Citováno 2019-08-15.
- ^ Pollack, Robert (2000). Msgstr "Závisle napsané záznamy pro reprezentaci matematické struktury". Věta prokazující logiku vyšších řádů, 13. mezinárodní konference. TPHOLs 2000. Springer. str. 462–479. doi:10.1007/3-540-44659-1_29.
- ^ Stump, Aaron (2018). "Od realizovatelnosti k indukci prostřednictvím závislé křižovatky". Annals of Pure and Applied Logic. 169 (7): 637–655. doi:10.1016 / j.apal.2018.03.002.
- ^ "C # průvodce". Citováno 2019-08-08.
- ^ „Discussion: Union and Intersection types in C Sharp“. Citováno 2019-08-08.
- ^ „Eclipse Ceylon: Welcom to Ceylon“. Citováno 2019-08-08.
- ^ „Typy křižovatek na Cejlonu“. Citováno 2019-08-08.
- ^ „F # Software Foundation“. Citováno 2019-08-08.
- ^ „Přidat typy křižovatek k F Sharp“. Citováno 2019-08-08.
- ^ „Tok: Kontrola statického typu pro JavaScript“. Citováno 2019-08-08.
- ^ „Syntaxe typu křižovatky v toku“. Citováno 2019-08-08.
- ^ Reynolds, J. C. (1988). Předběžný návrh programovacího jazyka Forsythe.
- ^ „Software Java“. Citováno 2019-08-08.
- ^ „IntersectionType (Java SE 12 & JDK 12)“. Citováno 2019-08-01.
- ^ „Programovací jazyk Scala“. Citováno 2019-08-08.
- ^ "Složené typy ve Scale". Citováno 2019-08-01.
- ^ „Typy křižovatek v Dotty“. Citováno 2019-08-01.
- ^ „TypeScript - JavaScript, který se mění“. Citováno 2019-08-01.
- ^ „Whiley: programovací jazyk s otevřeným zdrojovým kódem s rozšířenou statickou kontrolou“. Citováno 2019-08-01.
- ^ "Specifikace jazyka Whiley" (PDF). Citováno 2019-08-01.