Rodzaj – w teorii typów, schemat konstruktora typu. System rodzajów jest najczęściej rachunkiem lambda z typami prostymi, wyposażonym w typ pierwotny, oznaczony jako i nazywany „typem”, który jest rodzajem dowolnego typu danych, który nie wymaga parametryzacji.

Ponieważ operatory typów wyższego rzędu są rzadko spotykane w językach programowania, w większości praktyk programistycznych rodzaje są używane do rozróżnienia typów danych od konstruktorów typów używanych do implementacji polimorfizmu parametrycznego. Rodzaje pojawiają się, jawnie lub niejawnie, w językach, których systemy typów oferują programiście swobodny dostęp do polimorfizmu parametrycznego, przykładowo jak C++, Haskellu i Scali. Generics of a Higher Kind

Przykłady , wymawiane jako „typ”, jest rodzajem wszystkich typów danych. Przykładami typów rodzaju są całkowitoliczbowe typy danych, logiczne typy danych, a w funkcyjnych językach programowania typy monomorficznych funkcji. jest rodzajem jednoargumentowego konstruktora typu, przykładem czego może być lista. jest rodzajem konstruktora typu o dwóch parametrach (przekazywanych poprzez currying), przykładowo pary lub typu funkcji (nie mylić z wynikiem jego aplikacji, który jest „gotowym” typem funkcji, a więc rodzaju ). jest rodzajem unarnego operatora wyższego rzędu parametryzowanego jednoargumentowymi konstruktorami typów.Pierce (2002), chapter 32 Przykładem takiego operatora może być tablica mieszająca mapująca liczby na liczby parametryzowana typem kontenera („bucket”) użytego do rozwiązywania kolizji.

Rodzaje w Haskellu (Uwaga : dokumentacja Haskella używa tej samej strzałki zarówno dla typów, jak i rodzajów funkcji.)

System rodzajów Haskella 98 Kinds - The Haskell 98 Report obejmuje dokładnie dwa rodzaje:

, wymawiane "typ" to rodzaj wszystkich typów danych. jest rodzajem konstruktora typu, który przyjmuje typ rodzaju i produkuje rodzaj rodzaju .

Konstruktor typu przyjmuje jeden lub więcej argumentów by stworzyć końcowy typ danych. W ten sposób Haskell realizuje typy parametryczne. Przykładowo [] (lista) jest takim konstruktorem typu — by stać się pełnoprawnym typem potrzebuje jednego argumentu określającego typ elementów listy. Z tego powodu [Int] (lista liczb całkowitych), [Float] (lista liczb zmiennoprzecinkowych), a nawet [ [ Int ] ] (lista list liczb całkowitych) są prawidłowymi aplikacjami konstruktora typu []. Stąd można wywnioskować, że [] jest typem rodzaju . Ponieważ Int ma rodzaj , aplikacja [] do niego daje [Int], rodzaju .

Rekonstrukcja rodzajów Standardowy Haskell nie dopuszcza rodzajów polimorficznych, mimo pełnego wsparcia typów polimorficznych. Stąd w poniższym przykładzie:data Tree z = Leaf | Fork (Tree z) (Tree z)teoretycznie rodzaj parametru z może być dowolny, jednakże Haskell domyślnie zakłada, że parametry konstruktorów danych są opisywane przez typ rodzaju , chyba że deklaracja wprost wskazuje inaczej (patrz poniżej). Z tego powodu kompilator odrzuci następujące użycie Tree :type FunnyTree = Tree [] -- błądKonkretnie rzecz ujmując, rodzaj [], czyli , nie pasuje do domyślnego rodzaju z, czyli .

Operatory wyższych rzędów są w pełni akceptowane, jeśli tylko spełniają założenia kontroli rodzajów. Przykładowo:data App unt z = Z (unt z) ma rodzaj . To znaczy, że unt jest jednoargumentowym konstruktorem typu, którego parametr jest zwykłym typem ().

Warto nadmienić, że GHC oferuje rozszerzenie PolyKinds, które wraz z KindSignatures wprowadza rodzaje polimorficzne. Na przykład, następujący kod przechodzi kontrolę typów i rodzajów:data Tree (z :: k) = Leaf | Fork (Tree z) (Tree z) type FunnyTree = Tree [] -- OKOd wersji GHC 8.0.1 typy i rodzaje traktowane jak równoprawne koncepty.

Zobacz też System F

Przypisy

Kategoria:Typy danych