Евгений Котельников. Зависимые типы в haskell

17
Зависимые типы в Haskell Котельников Евгений SpbHUG/FProg 12 июля 2012

Upload: fprog

Post on 12-May-2015

660 views

Category:

Technology


7 download

DESCRIPTION

Системы зависимых типов позволяют оперировать данными на уровне типов, что может значительно повысить точность спецификации программ. Несмотря на отсутствие поддержки самих зависимых типов в Haskell, некоторые их свойства могут быть реализованы с помощью расширений языка. Будет представлен ряд техник, приближающий Haskell к возможностям языков вроде Agda, Coq и Epigram. Доклад имеет вводный характер и не требует предварительных знаний в обсуждаемых в нём темах.

TRANSCRIPT

Page 1: Евгений Котельников. Зависимые типы в Haskell

Зависимые типы в Haskell

Котельников Евгений

SpbHUG/FProg

12 июля 2012

Page 2: Евгений Котельников. Зависимые типы в Haskell

Типы и термы

В большинстве языков программирования существует какминимум два мира — мир термов и мир типов.

Мир типовInteger, String → String, ∀ Nat. Nat → String

Мир термов10, "foobar", n, \x -> x + 1, 6 + 5

Между объектами этих двух миров могут возникатьфункциональные зависимости.

Page 3: Евгений Котельников. Зависимые типы в Haskell

Типы и термы

Зависимость терма от терма

int increment(int x) {return x + 1 ;

}

Зависимость терма от типаПолиморфные функции

static <T> List<T> singletonList(T elem) {ArrayList<T> list = new ArrayList<T>( ) ;list.add(elem) ;return list ;

}

Page 4: Евгений Котельников. Зависимые типы в Haskell

Типы и термы

Зависимость типа от типаОператоры над типами

Collection <A>

Зависимость типа от термаЗависимые типы

nil : {A : Type} → Vector 0 Acons : {n : Nat} → {A : Type} →

Vector n A → Vector (n + 1) A

Page 5: Евгений Котельников. Зависимые типы в Haskell

Выражаемое в зависимых типах

I Операции над списками и матрицами сконтролируемыми размерностями

append : {n m : Nat} → {A : Type} →Vector n A → Vector m A → Vector (n + m) A

append nil ys = ysappend (cons x xs) ys = cons x (append xs ys)

I Отсортированные спискиI Сбалансированные деверьяI Функции с переменным числом аргументовI Типо-безопасные printf и scanf

Page 6: Евгений Котельников. Зависимые типы в Haskell

Код, содержащий доказательства

Системы зависимых типов порождают предикатную логику(см. соответствие Карри-Говарда). Тип — утверждение окоде, терм — доказательство.

Класс типа функтора в Coq

Class Functor (𝜑 : Type → Type) := {fmap : ∀ {𝛼 𝛽} , (𝛼→ 𝛽) → 𝜑 𝛼→ 𝜑 𝛽 ;

(** Functor laws **)fmap_id : ∀ 𝛼 (x : 𝜑 𝛼) , fmap id x = x ;fmap_comp : ∀ 𝛼 𝛽 𝛾 (x : 𝜑 𝛼) (f : 𝛽 → 𝛾) (g : 𝛼→ 𝛽) ,

fmap (f ∘ g) x = (fmap f ∘ fmap g) x} .

Экземпляры класса, помимо самой реализации fmap,обязаны предоставить доказательства теорем о ней.

Page 7: Евгений Котельников. Зависимые типы в Haskell

Экземпляр класса типа функтора

Instance list_functor : Functor list := {fmap 𝛼 𝛽 := fix fmap f xs := match xs with

| [] ⇒ []| x : : xs ⇒ (f x) : : (fmap f xs)end

} .Proof .(** fmap_id **)intros .induction x as [| x xs] .

reflexivity .rewrite IHxs . reflexivity .

(** fmap_comp **)intros .induction x as [| x xs] .

reflexivity .rewrite IHxs . reflexivity .

Qed .

Page 8: Евгений Котельников. Зависимые типы в Haskell

Вычисления в типах

Пример: умножение матриц

multiply : {n m q : Nat} →Matrix m n → Matrix n q → Matrix m q

ПроблемаНеобходимо на этапе компиляции проверить, что ширинаодной матрицы равна высоте другой. А в общем случае —проверить на равенство два терма.

Решение (?)Вычислить оба терма до достижения нормальной формы исравнивать их. Но вычисление может никогда незавершиться...

Page 9: Евгений Котельников. Зависимые типы в Haskell

Вычислительные модели в типах

Допускать только термы специального видаВместо редукций — разрешение системы ограничений.Dependent ML, ATS

Контроль над временем проверки типовЛимит на макс. допустимое количество шагов редукции.Cayenne

Сильная нормализацияОбщая рекурсия запрещена, везде тотальные функции.Coq

Отдельная проверка на тотальностьОбщая рекурсия разрешена, но отдельный механизмпытается распознать нетотальные функции.Agda, Epigram, Idris

Page 10: Евгений Котельников. Зависимые типы в Haskell

Зависимые типы в Haskell

ИдеяОпределить термы, структура которых повторяет структурусвоих типов.

Натуральные числа в арифметике Пеано

data Nat = Zero | Suc Nat

Натуральные числа как singleton types

data Zero = Zerodata Suc n = Suc n

Структура типа повторяет структуру терма

Suc Zero : : Suc ZeroSuc $ Suc $ Suc Zero : : Suc (Suc (Suc Zero) )

Page 11: Евгений Котельников. Зависимые типы в Haskell

Определение типа вектора

Обобщённые алгебраические типы данных

{-# LANGUAGE GADTs #-}{-# LANGUAGE GADTSyntax #-}

data Vector n a whereVNil : : Vector Zero aVCons : : a → Vector n a → Vector (Suc n) a

В типе вектора содержится длина

vec4 : : Vector (Suc (Suc (Suc (Suc Zero) ) ) ) Intvec4 = VCons 1 $ VCons 2 $ VCons 3 $ VCons 4 VNil

Page 12: Евгений Котельников. Зависимые типы в Haskell

Безопасные head и tail

Ограничение на длину задано в типе

vhead : : Vector (Suc n) a → avhead (VCons a _) = a

vtail : : Vector (Suc n) a → Vector n avtail (VCons _ v) = v

Проверка типов отвергает некорректные применения

vhead (VCons 1 $ VCons 2 VNil) -- okvhead VNil -- type error

vtail (VCons 1 $ VCons 2 VNil) -- okvtail VNil -- type error

Page 13: Евгений Котельников. Зависимые типы в Haskell

K-тый элемент вектора

Мультипараметрические классы типов

{-# LANGUAGE MultiParamTypeClasses #-}

class Kth n k wherekth : : Vector n a → k → a

instance Kth (Suc n’) Zero wherekth (VCons a _) _ = a

instance Kth n’ k’ ⇒ Kth (Suc n’) (Suc k’) wherekth (VCons _ v) (Suc k’) = nth v k’

Pattern matching по типам вместо термов

kth (VCons 1 $ VCons 2 $ VCons 3 VNil) (Suc $ Suc Zero) -- okkth (VCons 1 $ VCons 2 VNil) (Suc $ Suc $ Suc Zero) -- fail

Page 14: Евгений Котельников. Зависимые типы в Haskell

Конкатенация векторовСемейства типов{-# LANGUAGE TypeFamilies #-}type family Plus n mtype instance Plus Zero m = mtype instance Plus (Suc n’) m = Suc (Plus n’ m)

Можно инфиксно!

{-# LANGUAGE TypeOperators #-}type family n :+ mtype instance Zero :+ m = mtype instance (Suc n’) :+ m = Suc (n’ :+ m)

Конкатенация, сохраняющая длину

append : : Vector n a → Vector m a → Vector (n :+ m) aappend VNil v = vappend (VCons a w) v = VCons a (append w v)

Page 17: Евгений Котельников. Зависимые типы в Haskell

Вопросы?