Правильна термінологія в теорії типів: типи, конструктори типів, види / сорти та значення


14

У відповідь на попереднє запитання розпочалася невелика дискусія щодо правильної термінології для певних конструкцій. Оскільки я не знайшов питання (окрім того чи іншого , що не зовсім правильне), щоб вирішити це чітко, я роблю це нове.

Сумнівними термінами та їх взаємозв'язками є: тип, конструктор типу, параметр типу, види чи види та значення .

Я також перевірив вікіпедію на предмет теорії типів, але це теж не дуже прояснило її.

Тож заради хорошої відповіді та перевірки власного розуміння:

  • Як ці речі правильно визначені?
  • Яка різниця між цими речами?
  • Як вони пов’язані між собою?

Відповіді:


13

Добре, ходімо по черзі.

Цінності

Цінності - це конкретні дані, які програми оцінюють та жонглюють. Нічого фантазійного, деякі приклади можуть бути

  • 1
  • true
  • "fizz buzz foo bar"

Типи

Гарний опис для типу - це "класифікатор для значення". Тип - це трохи інформації про те, яке значення буде під час виконання, але вказане під час компіляції.

Наприклад, якщо ви скажете мені це e : boolпід час компіляції, і я знаю, що eце trueабо falseпід час виконання, нічого іншого! Оскільки типи класифікують такі величини, як це, ми можемо використовувати цю інформацію для визначення деяких основних властивостей вашої програми.

Наприклад, якщо я коли - небудь ви додавати eі e'коли e : intі e' : String, то я знаю , що - то відкусив! Насправді я можу позначити це і видавати помилку під час компіляції, кажучи: "Ей, це зовсім не має сенсу!".

Більш потужна система типу дозволяє отримати більш цікаві типи, які класифікують більш цікаві значення. Наприклад, розглянемо деяку функцію

f = fun x -> x

Це досить зрозуміло f : Something -> Something, але що це повинно Somethingбути? У системі нудного типу нам доведеться вказати щось довільне, наприклад Something = int. У гнучкішій системі типу, можна сказати

f : forall a. a -> a

Тобто, "для будь-яких a, fвідображає aна a". Це давайте скористаємося fбільш загально і пишемо цікавіші програми.

Більше того, компілятор перевірить, чи справді відповідає класифікатору, який ми йому дали, якщо f = fun x -> trueтоді у нас є помилка, і компілятор скаже так!

Так як tldr; type - обмеження у часі компіляції на значення, якими може бути вираз під час виконання.

Тип Конструктор

Деякі типи споріднені. Наприклад, список цілих чисел дуже схожий на список рядків. Це майже так, як sortдля цілих чисел майже як sortдля рядків. Ми можемо уявити собі якусь фабрику, яка будує ці майже однакові типи, узагальнюючи їхні відмінності та будуючи їх на вимогу. Ось що таке конструктор типів. Це як би функція від типів до типів, але трохи обмежена.

Класичний приклад - це загальний список. Конструктор типу для - це просто загальне визначення

 data List a = Cons a (List a) | Nil

Тепер Listце функція, яка відображає тип aдо списку значень цього типу! У Java-land я думаю, що це, можливо, називають "загальними класами"

Тип параметрів

Параметр типу - це просто тип, переданий конструктору типу (або функції). Так само, як і на рівні значення, ми би сказали, foo(a)має параметр, aяк List aі параметр типу a.

Види

Види трохи хитрі. Основна ідея полягає в тому, що певні типи схожі. Наприклад, у нас є всі примітивні типи в Java int, char, float... , які все поводяться так , як ніби вони мають один і той же «тип». За винятком випадків, коли ми говоримо про класифікатори для самих типів, ми називаємо види класифікаторів. Отже int : Prim, String : Box, List : Boxed -> Boxed.

Ця система дає приємні конкретні правила щодо того, які типи ми можемо використовувати де, як і те, як типи регулюють значення. Очевидно, це було б дурницею

 List<List>

або

 List<int>

У Java так Listпотрібно застосовувати конкретний тип, щоб використовувати його так! Якщо ми подивимось на їхні види List : Boxed -> Boxedта з тих пір Boxed -> Boxed /= Boxed, вищесказане - це своєрідна помилка!

Більшу частину часу ми насправді не думаємо про види, а просто ставимось до них як до "здорового глузду", але із системами більш вигадливого типу щось важливе думати.

Маленька ілюстрація того, що я говорив до цього часу

 value   : type : kind  : ...
 true    : bool : Prim  : ...
 new F() : Foo  : Boxed : ...

Краще для читання, ніж Вікіпедія

Якщо вас цікавлять подібні речі, я дуже рекомендую вкласти хороший підручник. Теорія типів і PLT взагалі досить велика і без цілісної бази знань ви (або, принаймні, я) можете блукати, не дістаючи нікуди місяцями.

Дві мої улюблені книги - це

  • Типи та мова програмування - Бен Пірс
  • Практичні основи мов програмування - Боб Гарпер

Обидві це чудові книги, які представляють те, про що я тільки говорив, і багато іншого в красивих, добре пояснених деталях.


1
Типи - це набори? Мені більше подобається "класифікатор", але ти не пояснюєш, що це означає, і без хорошого розуміння того, що таке тип, решта твоєї відповіді падає на спад.
Роберт Харві

@RobertHarvey Як це виглядає зараз, я відмовився від усіх згадок про набори :)
Daniel Gratzer

1
Набагато краще ....
Роберт Харві

@RobertHarvey Я вважаю погляд на типи як набори дуже інтуїтивним. Напр. Тип intу Java складається з набору 2 ^ 64 різних значень. Аналогія з множинами руйнується, коли підтипи включаються, але це досить хороша початкова інтуїція, особливо якщо врахувати алгебраїчні типи даних (наприклад, об'єднання двох типів може містити будь-якого з членів будь-якого типу; це об'єднання цих наборів) .
Doval

@Doval: Якщо я напишу клас, який описує Клієнта, він, ймовірно, представлятиме "набір" клієнтів, оскільки я збираюся скласти колекцію екземплярів. Але сказати, що Клієнт - це тип, оскільки він описує "набір" клієнтів - це тавтологія; здається очевидним. Що цікавіше, що тип замовника описує характеристики замовника. Використання "set" для пояснення цього видається більш ... абстрактним, ніж є насправді. Якщо, мабуть, ви не математик.
Роберт Харві

2

Як ці речі правильно визначені?

Вони правильно визначені жорсткою, академічною математичною підкладкою, що дає чітке твердження щодо того, що вони є, як вони працюють і що гарантується.

Але програмістам багато в чому цього не потрібно знати. Їм потрібно зрозуміти поняття.

Цінності

Почнемо з цінностей, оскільки все будується звідти. Значення - це дані, що використовуються при обчисленні. Залежно від підходу, це значення, з якими всі знайомі: 42, 3.14, "Як зараз коричнева корова", кадровий облік для Дженні за бухгалтерією тощо.

Інші інтерпретації значень є символами . Більшість програмістів розуміють, що ці символи є "значеннями" перерахунку. Leftі Rightє символами для перерахунків Handedness(ігнорування амбітних людей та риб).

Незалежно від реалізації значеннями є різні речі, з якими працює мова для виконання обчислень.

Типи

Проблема зі значеннями полягає в тому, що не всі обчислення є законними для всіх значень. 42 + goatнасправді не має сенсу.

Тут грають типи. Типи - це метадані, які визначають підмножини значень. HandednessПерерахування вище , є хорошим прикладом. Цей тип говорить "лише Leftі Rightтут можна використовувати". Це дозволяє програмам дуже рано визначати, що певні операції призведуть до помилок.

Ще одне практичне використання, яке слід врахувати, - це те, що під кришкою комп'ютери працюють з байтами. Байт 42 може означати число 42, або він може означати символ *, або це може означати Дженні з Бухгалтерського обліку. Типи також (у практичному використанні, не так теоретично) допомагають визначити кодування базової колекції байтів, що використовується комп'ютерами.

Види

І ось ми з вами трохи починаємо їздити. Отже, коли мова програмування має змінну, яка відноситься до типу, який тип він має?

Наприклад, у Java та C # він має тип Type(який має тип Type, який має ... і так далі). Це поняття, що стоїть за видами . У деяких мовах ви можете зробити трохи більше корисних речей із змінною Type, ніж Java та C #. Як тільки це відбудеться, буде корисно сказати : «Я хочу , що значення має тип, але також деякі роду з IEnumerable<int>». Та-да! Види.

Більшість програмістів можуть мислити такі види, як обмеження Java та C #. Розглянемо public class Foo<T> where T: IComparable{}. Мовою з видами T: kindOf(IComparable)декларація змінної стає законною; не просто особлива річ, яку ви можете зробити в оголошеннях класів і функцій.

Тип Конструктори

Можливо, не дивно, що конструктори типів - це просто конструктори для типів . "Але як ви конструюєте тип? Типи просто є ." Е ... не так вже й багато.

Крім того, не дивно, що досить складно побудувати всі різні корисні підмножини значень, які будь-коли використовуватиме комп'ютерна програма. Конструктори типів працюють, щоб допомогти програмістам "складати" ці підмножини змістовно.

Найбільш поширеним прикладом конструктора типу є визначення масиву: int[4]. Тут ви вказуєте 4конструктор типів, який використовує значення для створення вам масиву ints з 4-ма записами. Якщо ви вказали інший тип введення, ви отримаєте інший тип виводу.

Генеріки - це ще одна форма конструктора типів, яка бере свій внесок іншого типу.

У багатьох мовах існує конструктор типів, як P -> Rпобудувати тип, який представляє функцію, яка приймає тип Pі повертає тип R.

Тепер контекст визначатиме, чи "функція, яка повертає тип", є конструктором типу чи ні. У моєму (правда, обмеженому) досвіді, рядок - "чи можете ви використовувати цей тип під час компіляції?". Так? Тип конструктора. Ні? Просто функція.

Тип Параметр

Отже, ви пам’ятаєте параметри, передані конструкторам типів? Вони широко відомі як параметри типу, оскільки загальною формою конструктора типу є Type[param]або Type<param>.


1
Чи можете ви уточнити / розширити розділ про "Види"? У Haskell тип має вид *, тоді як конструктор типу (з одним аргументом) має вид * -> *. Такі обмеження, як (Num a) => a(тобто "будь-який тип, aякий є екземпляром класу Numтипу"), самі по собі не є видами. Клас типу Numне є самим "родом", але має такий тип * -> Constraint. Мені важко пов'язати ідею Хаскелла про "вид" (який, я вважаю, тісно пов'язаний з видами в теорії типів?) З прикладами, які ви даєте.
Іван Варфоломій

Я повинен сказати, :kindкоманда ghci дає такий тип Numяк * -> Constraint. Це може бути специфічно для GHC, я не знаю.
Іван Варфоломій

@JohnBartholomew - Види Haskell - це більше "підписів для конструкторів типів". На жаль, мій Haskell майже не до того, коли мені було б зручно говорити надто детально.
Теластин
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.