Haskell Type System with Dzmitry Ivashnev

Preview:

DESCRIPTION

Slides from http://www.meetup.com/fsharpminsk/events/176930252/?comment_table_id=344084692&comment_table_name=event_comment

Citation preview

Haskell Type System

Ивашнёв Дмитрийemail: 0xff0x666@gmail.com

jabber: xffox@headcounter.org

25 апреля 2014 г.

Парадигма

• Функциональный язык (functional)• Чисто функциональный язык (purely functional)• Язык с ленивой моделью вычислений (lazy)• Язык со статической типизацией (static typing)• Язык со строгой типизацией (strong typing)

Функциональный язык (functional)

fact(n) =

{1 if n = 0n × fact(n − 1) otherwise

Функциональный язык (functional)

module Factwhere

fact 0 = 1fact n = n*fact (n-1)

Чисто функциональный язык (purelyfunctional)

Представьте что все const

Чисто функциональный язык (purelyfunctional)

f (x) = ax2 + bx + c

Решить для x при f (x) = 0

∆ = b2 − 4ac

x1,2 =−b ±

√∆

2a

Чисто функциональный язык (purelyfunctional)

module Discriminantwhere

solveQuadratic a b c =let d = b*b - 4*a*c

in if d < 0 then []else if d == 0 then [-b/(2*a)]else [-b + (sqrt d)/(2*a), -b - (sqrt d)/(2*a)]

Чисто функциональный язык (purelyfunctional)

d = b * b - 4 * a * c

Списки (lists)

• [] - пустой список• [1, 2, 42] - список с тремя элементами• [[], [1], [1, 2], [1, 2, 42]] - список списков

Списки (lists)

• [1, 2 .. 5] = [1, 2, 3, 4, 5]• [1, 2 .. ]• [1 .. ]

Списки (lists)

Добавление в список42:[][42]

8:[42][8,42]

Списки (lists)

Сложность операцийlength - O(n)Проверка на пустой список: nullНе используйте length ls == 0Привет C++ и .empty() из STL

Функции первого порядка

Функции могут передаваться в качестве параметров функцийodd 1True

filter odd [1, 2, 3][1, 3]

Язык с ленивой моделью вычислений(lazy)

filter odd [1, 2, 3, 4, 5]

filter odd [1, 2 .. 5]

[1, 3, 5]

Язык с ленивой моделью вычислений(lazy)

filter odd [1 ..]

take 3 (filter odd [1 ..])

[1, 3, 5]

Язык со статической типизацией (statictyping)

Проверка типов на этапе компиляции

Язык со строгой типизацией (strongtyping)

Явные приведения между всеми типамиInt, Float, ...

С чего начать

http://www.haskell.org/Компиляторhttp://www.haskell.org/ghc/

Математическая нотация

Множества A и BФункция F

F : A→ B

Нотация типов в Haskell

Переменные типов: a и bВ данном случае на типы не накладывается никакихограниченийФункция f

f :: a -> b

Примеры

Переменные типов: a, b и cФункция f

f :: a -> b -> c

Спискиf :: a -> [a]

Функции первого порядка

filter :: (a -> Bool) -> [a] -> [a]map :: (a -> b) -> [a] -> [b]foldr :: (a -> b -> b) -> b -> [a] -> b

Логика типов

Определение тела функции по ее типуf :: a -> a

Логика типов

Определение тела функции по ее типуf :: a -> a

Возможное решениеf a = a

f = id

id 4242

Логика типов

Какие возможны реализации?f :: a -> [a]

Выведение типов

Для функции factmodule Factwhere

fact 0 = 1fact n = n*fact (n-1)

получим типfact :: (Eq a, Num a) => a -> a

Выведение типов

Все типы функций могут быть выведены автоматически наэтапе компиляцииЯвное указание типа может помочь в отладкеСкомпилировалось – работает (joke)

Выведение типов

C++11 добавляет выведение типа переменных – autoauto value = 42;auto value = 1 + 2;auto value = f(42);

C++14 добавляет выведение типа, возвращаемого функцией –auto

auto foobar(int value){

return value + 1;}

Алгебраические типы данных (AlgebraicData Types)

Наиболее общий составной тип, представляющий собойтип-сумму из типов-произведений (wikipedia)

Тип с одним параметром

Множество AПеременная типа a

data Name a = Constructor a

Тип с несколькими параметрами

Множества T, A и BПеременные типа a и b

data Name a b = Constructor a b

тип-произведениеT = A× B

Тип с несколькими конструкторами

Множества T и AПеременная типа a

data Name a = ContructorF a | ContructorS a

тип-суммаAf = {(x , 1) : x ∈ A}

As = {(x , 2) : x ∈ A}

T = Af ∪ As

Все вместе

Множества T, A, BПеременные типа a и b

data Name a b = ContructorF a b | ContructorS a

сумма произведений

Af = {(x , 1) : x ∈ A× B}

As = {(x , 2) : x ∈ A}

T = Af ∪ As

Дизъюнктное объединение (Disjointunion)

⋃i∈I{(x , i) : x ∈ Ai}

Зачем

• Формальное обощение: enum, struct, union• Сопоставление параметров функций по шаблону

Параметры функций

data State a b = First a | Second b | Third a b

handle (First s) v = Second (f s)handle (Second s) v = First shandle (Third s t) v = Third s (f t v)

enum

data Bool = True | Falsedata Color = Red | Green | Blue

enum Bool{

TRUE ,FALSE

};

struct

data State a b = St a b

struct State{

int a;int b;

};

union

data State a b = First a b | Second a

union State{

struct{

int a;int b;

} first;struct{

int a;} second;

};

Рекурсивные типы данных

Бинарное деревоmodule Treewhere

data Tree a = Leaf | Node (Tree a) a (Tree a)

sumTree Leaf = 0sumTree (Node left v right) = sumTree left + v + sumTree right

import Tree

main =putStrLn $ show (sumTree (Node (Node (Leaf) 2 (Node (Leaf) 3 (Leaf))) 1 (

Leaf)))

6

Списки

List a = [] | (:) a (List a)

Полиморфизм

Позволяет строить суждения о типах зная только класс этихтиповКласс описывает функции, реализуемые типом

Typeclasses

Моноид - множество с заданной на нем ассоциативнойбинарной операцией и нейтральным элементом.

(a · b) · c = a · (b · c)

a · e = a

Пример: целые числа с операцией умножения.Что насчет чисел с плавающей запятой?

Typeclasses

module Monoidwhere

class Monoid a wherebinop :: a -> a -> aidentity :: a

twice :: Monoid a => a -> atwice a = binop a a

Typeclasses

“In fact, trolls traditionally count like this: one, two, three . . .many, and people assume this means they can have no grasp ofhigher numbers.” – Men at Arms, Terry Pratchett

Typeclasses

module TrollNum(TrollNum (..), plus , binop , identity)where

import Monoid

data TrollNum = Zero | One | Two | Three | Manyderiving Show

plus :: TrollNum -> TrollNum -> TrollNumplus a b = fromNum (toNum a + toNum b)

instance Monoid TrollNum wherebinop = plusidentity = Zero

toNum Zero = 0toNum One = 1toNum Two = 2toNum Three = 3toNum Many = 4

fromNum 0 = ZerofromNum 1 = OnefromNum 2 = TwofromNum 3 = ThreefromNum _ = Many

Typeclasses

import Monoidimport TrollNum

main = putStrLn $ show $ twice Two

Many

Операторы

Среднее арифметическоеmodule Opswhere

(-|-) a b = (a + b)/2

Pointfree style

Функции f (x), g(x) и z(x)z(x) = f (g(x))

z = f . g(.) :: (b -> c) -> (a -> b) -> a -> c

Pointfree style

Функция, прибавляющая 1 к переданному значениюaddOne v = v + 1addOne v = (+) v 1addOne v = (+) 1 vaddOne = (+) 1((+)1) :: Num a => a -> a

Pointfree style

Найти длину самого длинного слова в строкеmodule LongestWordwhere

longestWord = (foldr max 0) . (map length) . words

Привет map-reduce

Понятие

Это абстракция линейной цепочки связанных вычислений. Еёосновное назначение - инкапсуляция функций с побочнымэффектом от чистых функций, а точнее их выполнений отвычислений (wikipedia).

Info

class Monad m where(>>=) :: m a -> (a -> m b) -> m b(>>) :: m a -> m b -> m breturn :: a -> m afail :: String -> m a

Общий шаблон

• Тип с одним параметром m• Получение значения (bind):функция (»=) :: m a -> (a -> m b) -> m b

• Инъекция значения (inject):функция return :: a -> m a

Monad

IO

Как возможно IO в системе без побочных эффектов?IO monad

Снова факториал

Хвостовая рекурсияmodule XFactwhere

xfact n = xfact ’ 1 nwhere

xfact ’ v 0 = vxfact ’ v n = xfact ’ (v*n) (n-1)

Выведение типов

Модульная арифметикаmodule ModIntwhere

newtype ModInt = ModInt {fromModInt :: Int

}deriving (Show)

instance Num ModInt where(+) (ModInt a) (ModInt b) = ModInt ((a + b) ‘mod ‘ 23)(*) (ModInt a) (ModInt b) = ModInt ((a * b) ‘mod ‘ 23)abs (ModInt a) = ModInt (abs a)signum (ModInt a) = ModInt (signum a)fromInteger v = ModInt (fromInteger v ‘mod ‘ 23)

import ModInt

pow a 0 = 1pow a b = a * pow a (b-1)

main = putStrLn $ show $ fromModInt $ pow 2 5

9

DSL

import Fuzzimport DumbFuzzer

authRequest = "AUTH" ‘wait ‘ authResponsesgetRequest = "GET" ‘wait ‘ getResponsesauthResponses = ("AUTHED" |-> getRequest) // (other (report 0))getResponses = ("200␣OK" |-> report 1) // ("418␣I’m␣a␣teapot" |-> report 42) //

(other (report 0))

main = dor <- fuzz DumbFuzzer authRequestputStrLn $ show r

Fuzz I

module Fuzz(wait , report , (|->), (//), other , fuzz , Fuzzer (..))where

data Response r = Response (Msg , Request r) | Other (Request r)data Request r = Send Msg [Response r] | Report r

report :: r -> Request rreport r = Report r

wait :: Msg -> [Response r] -> Request rwait message reactions = Send message reactions

other :: Request r -> [Response r]other response = [Other response]

(|->) :: Msg -> Request r -> [Response r](|->) message action = [Response (message , action)]

(//) :: [Response r] -> [Response r] -> [Response r](//) a b = a ++ b

fuzz :: Fuzzer f => f -> Request r -> IO rfuzz f (Send msg responses) = do

r <- send f msgnext f r responses

fuzz f (Report r) = return r

class Fuzzer f wheresend :: f -> Msg -> IO Msg

Fuzz II

next f _ [Other request] = fuzz f requestnext f resp ((Other request):rs) = next f resp (rs ++ [Other request ])next f resp (( Response (msg , request)):rs) | resp == msg = fuzz f request

| otherwise = next f resp rs

type Msg = String

Fuzzer

module DumbFuzzerwhere

import Fuzz

data DumbFuzzer = DumbFuzzer

instance Fuzzer DumbFuzzer wheresend _ m = do

putStrLn mgetLine

Литература

• Real World Haskell by Bryan O’Sullivan, John Goerzen, andDon Stewart

• The Haskell Road to Logic, Math and Programming by KeesDoets and Jan van Eijck

• Parallel and Concurrent Programming in Haskell by SimonMarlow

• Haskell Beats C Using Generalized Stream Fusion by GeoffreyMainland, Roman Leshchinskiy, and Simon Peyton Jones(paper)

Recommended