Дозвольте мені компенсувати початок деякої цієї плутанини, врізавшись у деяку розбірливість. Мені подобається використовувати аналогію до рівня цінності, щоб пояснити це, оскільки люди, як правило, більш знайомі з цим.
Конструктор типу - це тип, який можна застосувати до аргументів типу, щоб "сконструювати" тип.
Конструктор значень - це значення, яке можна застосувати до аргументів значення, щоб "сконструювати" значення.
Конструктори значень зазвичай називають "функціями" або "методами". Ці "конструктори" також називаються "поліморфними" (тому що вони можуть бути використані для побудови "речей" різної "форми") або "абстракцій" (оскільки вони абстрагуються над тим, що варіюється між різними поліморфними інстанціями).
У контексті абстракції / поліморфізму, перший порядок означає "одноразове використання" абстракції: ви абстрагуєтесь над типом один раз, але сам тип не може абстрагуватися ні над чим. Загальна версія Java 5 - це перше замовлення.
Інтерпретація вищезазначених характеристик абстракцій першого порядку:
Конструктор типу - це тип, який можна застосувати до аргументів власного типу, щоб "сконструювати" належний тип.
Конструктор значень - це значення, яке ви можете застосувати до власних аргументів значення, щоб "побудувати" власне значення.
Щоб підкреслити, що тут немає жодної абстракції (я думаю, ви могли б назвати це "нульовим порядком", але я цього не використовував ніде), наприклад, значення 1
або тип String
, ми зазвичай кажемо, що це "належне" значення або тип.
Власне значення є "негайно придатним для використання" в тому сенсі, що воно не чекає аргументів (воно не абстрагується над ними). Розгляньте їх як значення, які ви можете легко роздрукувати / перевірити (серіалізація функції - це обман!).
Правильний тип - це тип, який класифікує значення (включаючи конструктори значень), конструктори типів не класифікують жодних значень (їх спочатку потрібно застосувати до аргументів правого типу, щоб отримати належний тип). Щоб придумати тип, необхідно (але недостатньо), щоб він був належним типом. (Це може бути абстрактний клас або клас, до якого ви не маєте доступу.)
"Вищий порядок" - це просто загальний термін, що означає багаторазове використання поліморфізму / абстракції. Це означає те ж саме для поліморфних типів і значень. Конкретніше, абстракція вищого порядку абстрагує щось, що абстрагує щось. Для типів термін "вищий рід" - це версія спеціального призначення більш загального типу "вищого порядку".
Таким чином, версія нашої характеристики вищого порядку стає:
Конструктор типу - це тип, який можна застосувати до аргументів типу (належних типів або конструкторів типів), щоб "сконструювати" належний тип (конструктор).
Конструктор значень - це значення, яке ви можете застосувати до аргументів значення (власне значення або конструктори значень), щоб "сконструювати" власне значення (конструктор).
Таким чином, "вищого порядку" просто означає, що, коли ви говорите "абстрагування над X", ви насправді це маєте на увазі! Те, X
що абстрагується, не втрачає власних "прав на абстракцію": воно може абстрагувати все, що хоче. (До речі, я використовую тут дієслово "абстракт", щоб означати: залишити те, що не є суттєвим для визначення значення чи типу, щоб воно могло бути змінено / надано користувачем абстракції як аргумент .)
Ось декілька прикладів (натхненні запитаннями Луца електронною поштою) правильних значень та типів першого порядку та вищого порядку:
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]})#λ
Де використовувані класи були визначені як:
class String
class List[T]
class Functor[F[_]]
Щоб уникнути непрямості через визначення класів, вам потрібно якось виразити функції анонімного типу, які не виражаються безпосередньо в Scala, але ви можете використовувати структурні типи без занадто синтаксичних накладних витрат ( #λ
стиль - завдяки https://stackoverflow.com / користувачів / 160378 / ретронім afaik):
У деякій гіпотетичній майбутній версії Scala, яка підтримує функції анонімного типу, ви можете скоротити цей останній рядок із прикладів до:
types (informally) String [x] => x [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be
(В особистій записці я шкодую, що коли-небудь говорив про "типи вищого роду", адже вони просто типи! Зрештою, коли вам абсолютно потрібно роз'єднуватись, я пропоную сказати такі речі, як "тип конструктора типу", "тип конструктора типу" або "псевдонім конструктора", щоб підкреслити, що ви не говорите лише про належні типи.)
ps: Для подальшого ускладнення питань "поліморфність" неоднозначно по-іншому, оскільки поліморфний тип іноді означає універсально кількісний тип, наприклад Forall T, T => T
, який є належним типом, оскільки він класифікує поліморфні значення (у Scala це значення може бути написано як структурний тип {def apply[T](x: T): T = x}
)