Системы типов
в двух словах
Вячеслав Шебанов
Disclaimer
Зачем нужны типы?
Слово (Word)
1011010001001010100011110101010
Слова имеют смысл
Но этот смысл задается внешней системой
Типы появляются естественным образом
лорд Бертран Рассел
“Пусть в некой деревне живёт брадобрей, который бреет всех жителей деревни, которые не бреются сами, и только их.
Бреет ли брадобрей сам себя?
Парадокс Брадобрея
Теория типов Рассела
Примитивные типы
let isDone: boolean = false;
let someNumber: number = 10;
Зачем нужны типы?
Чтобы в вашей программе не было парадоксов (ошибок)
Давид Гильберт
Entscheidungsproblem
Проблема разрешимости
Можем ли мы, описав некое утверждения специальным образом, ответить на вопрос с помощью общего метода является ли это утверждение истиной всегда
Алонзо Черч
λ-исчисление
- x, y, a-z — переменная
- M, N, A-Z — терм (выражение)
- λx.M — абстракция (анонимная функция)
- (M N) — применение (вызов функции)
λ-исчисление
(λx . x) z
(λx . x) z → z
(λx. x) (λx. x)
(λx. x) (λx. x) → (λx. x)
Identity function
function identity(x) {
return x;
}
А как же типы?
Простое типизированное λ-исчисление
λ→
(λx:Bool . x):Bool
Simply-Typed Lamda Calculus
function identity(x: number): number {
return x;
}
(λx:Int y:Int . x * y): Int
function mult(x: number, y: number): number {
return x * y;
}
Полиморфизм
function saySomething(cat: Cat) {
return 'Meow';
}
function saySomething(dog: Dog) {
return 'Woof';
}
function saySomething(cat: Cat) {
return 'Meow';
}
function saySomething(dog: Dog) {
return 'Woof';
}
> saySomething(cat);
"Meow"
> saySomething(dog);
"Woof"
function identity<T>(arg: T): T {
return arg;
}
System F
Жирар 1972, Рейнольдс 1974
Абстракция на типах
λx:Bool . x
λX. λx:X. x
Абстракция на типах
id = λX. λx:X. x
Абстракция на типах
|> id : ∀X. X → X
Абстракция на типах
(λX. λx:X. x) Bool
Абстракция на типах
λx:Bool. x
Дженерики в Go
func Print[T any](s []T) {
for _, v := range s {
fmt.Println(v)
}
}
Print[int](arrayOfInts)
*вы находитесь здесь*
Расширения
(Records)
struct Person
{
char name[50];
int age;
float salary;
};
Как понять, что в самой системе типов нет ошибок?
Soundness
- Прогресс
- Сохранение типов
Прогресс
(λx:Int y:Int . x * y) a b
Если a и b это Int
Сохранение типов
(λx:Int y:Int . x * y) a b
→
a * b
Когда добавляешь новую фичу в язык
Java and Scala’s Type Systems are Unsound
(2016 Amin, Tate)
Вернемся в 1937
Алан Тьюринг
Проблема останова
Даны описание процедуры и её начальные входные данные, требуется определить, завершится ли когда-либо выполнение процедуры с этими данными.
Тезис Черча-Тьюринга
Любая функция, которая может быть вычислена физическим устройством, может быть вычислена машиной Тьюринга
Тьюринг-полнота
Строгая нормализация
Простое типизированное лямбда-исчисление
System F
Тотальность
Тотальной называется такая функция, которая гарантированно завершается за конечное количество шагов и определена на всех разрешенных входных параметрах
Тотальность
Хенк Барендрехт
λ-куб
Можно типизировать функции
function identity(x: Bool): Bool {
return x;
}
Можно типизировать полиморфизм
function identity<T>(x: T): T {
return x;
}
Можно использовать функции на уровне типов
Типы высшего рода (Higher Kinded Types) и семейства типов (Type Families) в Haskell
Можно использовать значения переменных на уровне типов
function random(n: Nat) : Fin<n> {
return ...;
}
Хотите подробнее?
Задавайте вопросы после доклада!
Верификация ПО
Что это значит?..
Можно писать код без ошибок!
Соответствие Карри-Говарда
Линейные типы
Продолжаем заимствования из логики
Линейные типы
let x = vec![1, 2, 3];
let y = x; // NOTE: x moved here
println!("{:?}", x); // ERROR: use of moved value x
pritnln!("{:?}", y); // OK
Еще непонятнее
HoTT и Кубические типы
Послесловие
Ссылки
normal
- https://www.manning.com/books/type-driven-development-with-idris — Type-Driven Development with Idris
- https://mitpress.mit.edu/books/little-typer — свежая книга из серии Little * про типы и завтипы в частности
- https://corecursive.com/021-gods-programming-languagewith-philip-wadler/ — подкаст про типы с Уодлером
-
http://theannotatedturing.com/ — книга про работу Тьюринга, про работу над проблемой разрешимости. С историческими справками и большим количеством контекста
-
https://hackernoon.com/java-is-unsound-28c84cb2b3f — про то, что у Java и Scala unsound системы типов
-
https://compsciclub.ru/courses/Glasgow-Haskell-Compiler/2018-spring/ — лекции про то, как устроен компилятор Haskell и его теоретические основы
-
https://compsciclub.ru/courses/systemsoftypedlambdacalculi/2011-spring/ — лекции про типизрованное лямбда-исчисление
-
https://gitlab.haskell.org/ghc/ghc/-/wikis/linear-types/roadmap — Роадмап имплементации ли нейных типов в Haskell
Ссылки
hard
- http://lucacardelli.name/Papers/OnUnderstanding.A4.pdf — крутое вступление про классификацию ЯП, полиморфизма и немного истории. 1 глава (дальше жесть)
- https://www.cis.upenn.edu/~bcpierce/tapl/ — классическая книга для ввода в теорию типов
- https://www.itu.dk/courses/BPRD/E2009/fundamental-1967.pdf — первая серьезная работа по полиморфизму в языках программирования
-
http://homepages.inf.ed.ac.uk/wadler/papers/propositions-as-types/propositions-as-types.pdf — снова Уодлер, про Карри-Говарда и историю. Можно видео (https://www.youtube.com/watch?v=IOiZatlZtGU)
-
https://softwarefoundations.cis.upenn.edu/ — похоже на TAPL, но с уклоном в практику
-
https://github.com/namin/unsound/blob/master/doc/unsound-oopsla16.pdf — пейпер про unsoundness Java и Scala
Ссылки
nightmare
- https://people.mpi-sws.org/~dreyer/tor/papers/wadler.pdf — Уодлер про теоремы, которые можно получить из полиморфных функций
-
https://pdfs.semanticscholar.org/3076/c162530c8a859e4c89556ede4783465430fb.pdf?_ga=2.81413716.276970782.1540919121-786323898.1540919121 — оригинальная работа про лямбда-куб
-
http://typetheorypodcast.com/ — подкаст про теорию типов, всего 6 выпусков
Конец
Twitter: @thought_sync
Зависимые типы
за 5 минут
function zip<T1, T2>(list1: Array<T1>, list2: Array<T2>): Array<Pair<T1, T2>> {
if (list1.length !== list2.length) {
throw Error('Arrays lengths are not equal');
}
let result = [];
for (let i = 0; i < list1.length; i++) {
result[i] = pair(list1[i], list2[i]);
}
return result;
}
function zip<T1, T2>(list1: Array<T1>, list2: Array<T2>)
Array<Pair<T1, T2>>
if (list1.length !== list2.length) {
throw Error('Arrays lengths are not equal');
}
let result = [];
for (let i = 0; i < list1.length; i++) {
result[i] = pair(list1[i], list2[i]);
}
return result;
Более точный тип
Vect<T, n>
T — тип элемента
n — кол-во элементов
function zip<T1, T2>(v1: Vect<T1, n>, v2: Vect<T2, n>): Vect<Pair<T1, T2>, n> {
let result = [];
for (let i = 0; i < n; i++) {
result[i] = pair(v1[i], v2[i]);
}
return result;
}
function zip<T1, T2>(v1: Vect<T1, n>, v2: Vect<T2, n>)
Vect<Pair<T1, T2>, n>
Откуда берутся вектора?
function vectToList<T>(list: Array<T>) : DPair(n: Nat, Vect<T, n>) {
return dpair(list.length, toVect(list));
}
function vectToList<T>(list: Array<T>)
DPair(n: Nat, Vect<T, n>)
Зависимая пара
return dpair(list.length, toVect(list));
Системы типов в двух словах v2
By Slava Shebanov
Системы типов в двух словах v2
- 1,356