Co to jest typ wyższy kinded w Scali?

Można znaleźć w sieci:

  1. Higher kinded type = = konstruktor typu?

    class AClass[T]{...} // For example, class List[T]
    

    Niektórzy mówią, że jest to typ o wyższym pokrewieństwie, ponieważ abstrakty nad typami, które byłyby zgodne z definicją.

    typy wyższe są typami, które przyjmują inne typy i konstruują nowy typ

    Są one również znane jako konstruktor typu. (Np. w programowaniu w Scala ).

  2. Higher kinded type = = konstruktor typu który przyjmuje konstruktor typu jako parametr typu?

    W artykule Generyki Wyższego rodzaju można przeczytać

    ... typy abstrakcyjne nad typami abstrakcyjne nad typami ("typy o wyższym pokrewieństwie")..."

    Co sugeruje, że

    class XClass[M[T]]{...} // or
    
    trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]]
    

    Jest typem o wyższym pokrewieństwie.

Więc mając to na uwadze, trudno jest odróżnić pomiędzy konstruktor typu, konstruktor typu wyższego typu i konstruktora typu , który przyjmuje konstruktory typu jako parametr typu , stąd pytanie powyżej.
Author: Ben Kovitz, 2011-06-06

4 answers

Pozwól mi nadrobić trochę zamieszania, rzucając się z jakimś disambiguation. Lubię używać analogii do poziomu wartości, aby to wyjaśnić, jak ludzie wydają się być bardziej zaznajomieni z nim.

Konstruktor typu jest typem, który można zastosować do argumentów typu, aby "skonstruować" Typ.

Konstruktor wartości jest wartością, którą można zastosować do argumentów wartości, aby "skonstruować" wartość.

Konstruktory wartości są zwykle nazywane "funkcjami" lub "metody". Te "konstruktory" są również określane jako " polimorficzne "(ponieważ mogą być używane do konstruowania" rzeczy "o różnym" kształcie") lub" abstrakcje " (ponieważ abstrakcyjne nad tym, co różni się między różnymi instancjami polimorficznymi).

W kontekście abstrakcji/polimorfizmu, pierwszy porządek odnosi się do" pojedynczego użycia " abstrakcji: raz abstrakujesz nad typem, ale sam typ nie może abstrakować nad niczym. Java 5 generics są pierwszego rzędu.

The first-order interpretacja powyższych cech abstrakcji to:

Konstruktor typu jest typem, który można zastosować do argumentów właściwego typu, aby "skonstruować" właściwy typ.

Konstruktor wartości jest wartością, którą można zastosować do argumentów właściwej wartości, aby "skonstruować" odpowiednią wartość.

Dla podkreślenia, że nie ma w tym żadnej abstrakcji (chyba można to nazwać "porządkiem zerowym", ale nigdzie tego nie widziałem), np. wartość 1 lub typ String, zwykle mówimy, że coś jest "właściwą" wartością lub typem.

Wartość właściwa jest "natychmiast użyteczna" w tym sensie, że nie czeka na argumenty (nie abstrakcja nad nimi). Pomyśl o nich jak o wartościach, które możesz łatwo wydrukować/sprawdzić (serializowanie funkcji to oszustwo!).

Typ właściwy jest typem, który klasyfikuje wartości (w tym konstruktory wartości), konstruktory typów nie klasyfikują żadnych wartości (najpierw muszą być zastosowane do właściwych argumentów typu, aby uzyskać odpowiedni typ). Aby utworzyć instancję typu, konieczne jest (ale nie wystarczające), aby był to właściwy typ. (Może to być klasa abstrakcyjna lub klasa, do której nie masz dostępu.)

"wyższego rzędu" jest po prostu terminem ogólnym, który oznacza wielokrotne użycie polimorfizmu / abstrakcji. To samo oznacza dla typów i wartości polimorficznych. Konkretnie, abstrakcja wyższego rzędu abstrakcje nad czymś, co abstrakcje nad czymś. W przypadku typów termin "wyżej spokrewniony" jest wersją specjalnego przeznaczenia bardziej ogólnego "wyższego rzędu".

Tak więc Wersja wyższego rzędu naszej charakterystyki staje się:

Konstruktor typu jest typem, który można zastosować do argumentów typu (typy właściwe lub konstruktory typu), aby "skonstruować" właściwy typ (konstruktor).

Konstruktor wartości jest wartością, którą można zastosować do argumentów wartości (odpowiednich wartości lub konstruktorów wartości), aby "skonstruować" odpowiednią wartość (konstruktor).

Tak więc "wyższego rzędu" po prostu oznacza to, że kiedy mówisz "abstrakcja nad X", naprawdę masz to na myśli! To X, które jest abstrakcyjne, nie traci własnych "praw abstrakcji": może abstrakować wszystko, czego chce. (Nawiasem mówiąc, używam tu czasownika "abstract", aby oznaczać: pominąć coś, co nie jest istotne dla definicji wartości lub typu, tak aby mogło być zmienione/dostarczone przez użytkownika abstrakcji jako argument.)

Oto kilka przykładów (zainspirowanych pytaniami Lutza pocztą elektroniczną) WŁAŚCIWEGO, pierwszorzędnego i wartości i typy wyższego rzędu:

                   proper    first-order           higher-order

values             10        (x: Int) => x         (f: (Int => Int)) => f(10)
types (classes)    String    List                  Functor
types              String    ({type λ[x] = x})#λ   ({type λ[F[x]] = F[String]})#λ

Gdzie używane klasy zostały zdefiniowane jako:

class String
class List[T]
class Functor[F[_]]

Aby uniknąć indrection poprzez definiowanie klas, musisz w jakiś sposób wyrazić anonimowe funkcje typu, które nie są expressible bezpośrednio w Scali, ale możesz używać typów strukturalnych bez zbytniego narzutu składniowego (styl jest spowodowany https://stackoverflow.com/users/160378/retronym afaik):

W jakiejś hipotetycznej przyszłej wersji Scali, która obsługuje funkcje typu anonimowego, można skrócić ostatnią linię z przykładów do:

types (informally) String    [x] => x              [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be

(osobiście żałuję, że kiedykolwiek mówiłem o "typach o wyższym pokrewieństwie", w końcu to tylko typy! Kiedy absolutnie musisz disambiguate, proponuję powiedzieć rzeczy takie jak "type constructor parameter", "type constructor member" lub "type constructor alias", aby podkreślić, że nie mówisz tylko o odpowiednich typach.)

Ps: aby jeszcze bardziej skomplikować sprawy, "polimorficzny" jest Typ polimorficzny oznacza typ powszechnie kwantyfikowany, np. Forall T, T => T, który jest typem właściwym, ponieważ klasyfikuje wartości polimorficzne (w Scali wartość ta może być zapisana jako typ strukturalny {def apply[T](x: T): T = x})

 239
Author: Adriaan Moors,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:20

(Ta odpowiedź jest próbą udekorowania odpowiedzi Adriaan Moors kilkoma graficznymi i historycznymi informacjami.)

[[12]}wyższe typy są częścią Scali od 2.5.
  • Przed tą scalą, jak Java do teraz, nie pozwalał na użycie konstruktora typu ("generics" w Javie) do wykorzystania jako parametr type do konstruktora type. np.

     trait Monad [M[_]]
    

    Nie było możliwe.

    W Scali 2.5 system typów został rozszerzony o możliwość klasyfikacji typy na wyższym poziomie (znany jako konstruktor typu polimorfizm ). Te klasyfikacje są znane jako rodzaje.

    Rodzaj i rodzaj realtion, * * pochodna * * od " Generics of a Higher Kind" (Obraz pochodzi z generyków Wyższego rodzaju )

    Konsekwencją jest to, że konstruktor typu (np. List) może być użyty podobnie jak inne typy w pozycji parametru typu konstruktorów typu i tak stały się one typami pierwszej klasy od czasów Scali 2.5. (Podobne do funkcji, które są wartościami pierwszej klasy w Scali).

    W kontekstu systemu typu obsługującego wyższe rodzaje, możemy rozróżnić typy właściwe , typy takie jak Int lub List[Int] od typów pierwszego rzędu, takich jak List i typy wyższego rodzaju, takie jak Functor lub Monad (typy abstrakcyjne nad typami abstrakcyjne nad typami).

    System typów Javy po drugiej stronie nie obsługuje typów i dlatego nie ma typów "wyższego rodzaju".

    więc to musi być postrzegane na tle typu wspierającego system.

  • W przypadku Scali często widzisz przykłady konstruktora typu jak

     trait Iterable[A, Container[_]]
    
    W 1999 roku, w ramach projektu, w ramach projektu, rozpoczęto prace nad nową wersją Scali dla programistów generycznych.]} W 1999 roku, w wyniku połączenia dwóch zespołów, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w 1999 roku, w]}

    Użycie Container jako parametru konstruktora typu wyższego (wyższego rzędu) typu tutaj Iterable.

 86
Author: Lutz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-12 08:57:01

Rodzaj zwykłych typów, takich jak Int i Char, których instancje są wartościami, to *. Rodzaj konstruktorów typu jednoargumentowego, takich jak Maybe to * -> *; konstruktory typu binarnego, takie jak Either mają (Curry) rodzaj * -> * -> * i tak dalej. Typy takie jak Maybe i Either można wyświetlać jako funkcje na poziomie typu: przyjmują one jeden lub więcej typów i zwracają Typ.

Funkcja jest wyższego rzędu jeśli ma rzędu większego niż 1, Gdzie porządek jest (nieformalnie) głębokość zagnieżdżania, po lewej stronie, strzałek funkcyjnych:

  • Order 0: 1 :: Int
  • kolejność 1: chr :: Int -> Char
  • zamówienie 2: fix :: (a -> a) -> a, map :: (a -> b) -> [a] -> [b]
  • kolejność 3: ((A -> B) -> C) -> D
  • rozkaz 4: (((A -> B) -> C) -> D) -> E

Tak więc, w skrócie, Typ wyższego rzędu jest tylko funkcją wyższego rzędu.

  • Order 0: Int :: *
  • kolejność 1: Maybe :: * -> *
  • Order 2: Functor :: (* -> *) -> Constraint - higher-kinded: converts unary type constructors to typeclass ograniczenia
 63
Author: Jon Purdy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-05 11:38:02

Powiedziałbym: Typ o wyższym pokrewieństwie abstrakuje nad konstruktorem typu. Np. rozważ

trait Functor [F[_]] {
   def map[A,B] (fn: A=>B)(fa: F[A]): F[B]
}

Tutaj Functor jest "typem o wyższym pokrewieństwie" (używanym w artykule "Generics of a Higher Kinded"). Nie jest to konkretny ("pierwszego rzędu") konstruktor typu, taki jak List (który abstrahuje tylko nad odpowiednimi typami). Abstrahuje on nad wszystkimi konstruktorami typu uniary ("pierwszego rzędu") (oznaczonymi przez F[_]).

Lub inaczej mówiąc: w Javie mamy wyraźnie konstruktory typu (np. List<T>), nie mamy jednak "typów o wyższym pokrewieństwie", ponieważ nie możemy nad nimi abstrakcji (np. nie możemy napisać interfejsu Functor zdefiniowanego powyżej - przynajmniej Nie bezpośrednio ).

Termin " polimorfizm wyższego rzędu (konstruktor typu)" jest używany do opisu systemów, które obsługują "typy o wyższym pokrewieństwie".

 28
Author: Landei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-21 17:35:20