Haskell*Александр Гранинgraninas@gmail.com*alpha version of presentation
HaskellScalaClojure...Want more????
О чем доклад?● Часть 1. Ликбез по ФП и Haskell○ Функциональное программирование○ Язык Haskell. Применимость языка○ Язык Ha...
Программирование:● Императивное● Объектно-ориентированное● Функциональное● Логическое● Декларативное
Задача:обратить слова в строкеThis is a end, my only friend!friend! only my end, the is This
Императивные языки
1. std::string words = "This is the end, myonly friend!";2. std::vector<std::string> swv;3. boost::split(swv, words, boost...
Объектно -ориентированные языки
Программирование в терминахвзаимодействия объектов1. List<String> ls = Arrays.asList("This is theend, my only friend!".spl...
Функциональные языки
Программирование в терминахтрансформации данныхunwords . reverse . words$ "This is the end, my only friend!"...Еще один пр...
(println "Hello World!")printfn "Hello World!"io:format("Hello, World!~n").putStrLn "Hello World!"println("Hello World!")
Функциональноепрограммирование● ...● ...● ...● ...● ...● ...?
Функциональноепрограммированиеfactorial n =if (n == 0)then 1else (n * factorial (n-1))ten = 10● Все есть функция● ...● ......
Функциональноепрограммированиеfib 0 = 0fib 1 = 1fib n = fib (n-1) + fib (n-2)● Все есть функция● Рекурсия● ...● ...● ...● ...
ФункциональноепрограммированиеnumberList = [1, 2, 3, 4, 5]modifyList func list = map func listsquare x = x * xdouble x = 2...
Функциональноепрограммированиеa := 1a := 2DO NOT CHANGE!The immutability is with you● Все есть функция● Рекурсия● Функции ...
Функциональноепрограммирование● Все есть функция● Рекурсия● Функции высшихпорядков● Иммутабельностьданных● Чистые функции●...
ФункциональноепрограммированиеfizzBuzz :: Int -> StringfizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| i...
Язык HaskellHaskell - это...● ...● ...● ...● ...● ...● ...● ...?
Язык HaskellHaskell - это...● Чистый функциональный,● строго статически типизированный,● кроссплатформенный,● компилируемы...
Краткая история Haskell● Хаскель Карри● Саймон Пейтон Джонс● Семейство языков ML● Прародитель - Miranda● 1990 год - Haskel...
Слабые стороны Haskell● Системное программирование● Real-time системы● Сложные системы со множествомпобочных эффектов● GUI
Сильные стороны Haskell● Обработка данных● Надежность и выразительность кода● Алгоритмика● Автоматическая и ручнаяпараллел...
FUNctionIts all Haskell is about
Success Stories?
Success StoriesAbstract Syntax TreeCode baseLex-pass
Success Stories● HaLVM● HaLFS● Copilot● Orc● ...
Success Stories
Success Stories
Success StoriesNgnTraffic
Success StoriesWantmore?http://www.haskell.org/haskellwiki/Haskell_in_industry
Haskell и популярность?
Haskell - не мэйнстрим?..
Haskell - не мэйнстрим?..
В России - не мэйнстрим...● Общее оставание развития - 20 лет● Низкое качество преподавания● Консервативный менталитет "зу...
Язык Haskell: Основы
Пара простых примеров
Числа Фибоначчиfib 0 = 0fib 1 = 1fib n = fib (n-1) + fib (n-2)
Сопоставление с образцомfib 0 = 0fib 1 = 1fib n = fib (n-1) + fib (n-2)
Факториалfact 0 = 1fact n = fact (n-1) * n
fact 0 = 1fact n = fact (n-1) * nСопоставление с образцом
Задача: FizzBuzzНапишите программу,которая выводит на экранчисла от 1 до 100.При этом вместо чисел,кратных трем, программа...
-- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fi...
-- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fi...
> fizzBuzz 1"1"> fizzBuzz 30"FizzBuzz"-- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDiv...
-- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fi...
-- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fi...
-- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fi...
module Main wherefizzBuzz x = if isDivided x 15then "FizzBuzz"else if isDivided x 5then "Buzz"else if isDivided x 3then "F...
module Main wherefizzBuzz x = case isDivided x 15 ofTrue -> "FizzBuzz"False -> case isDivided x 5 ofTrue -> "Buzz"False ->...
module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = sho...
module Main wherefizzBuzz :: Int -> StringfizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 ...
module Main wherefizzBuzz :: Int -> StringfizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 ...
Декларация типаfunc :: Int -> Int -> Bool1 2РезультатТип: Аргумент Аргумент3
module Main wherefizzBuzz :: Int -> StringfizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 ...
module Main wherefizzBuzz :: Int -> StringfizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 ...
Функции высших порядковfizzBuzz :: Int -> StringfizzBuzzes :: [String]fizzBuzzes = map fizzBuzz [1..100]
Функции высших порядковfizzBuzz :: Int -> StringfizzBuzzes :: [String]fizzBuzzes = map fizzBuzz [1..100]map :: (a -> b) ->...
Функции высших порядковmap :: (a -> b) -> [a] -> [b]fizzBuzz :: Int -> StringfizzBuzzes :: [String]fizzBuzzes = map fizzBu...
Полиморфизмmap :: (a -> b) -> [a] -> [b]a :: Intb :: StringfizzBuzz :: Int -> StringfizzBuzzes :: [String]fizzBuzzes = map...
ЛямбдыisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0
ЛямбдыisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0isDivided :: Int -> (Int -> Bool)isDivided x = n -> (...
ЛямбдыisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0isDivided :: Int -> (Int -> Bool)isDivided x = n -> (...
ЛямбдыisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0isDivided :: Int -> (Int -> Bool)isDivided x = n -> (...
Лямбдыx n -> (x `mod` n) == 0
Лямбдыx n -> (x `mod` n) == 0Аргументы Тело функции
module Main wheremain :: IO ()main = doputStrLn "Printing FizzBuzzes..."print fizzBuzzesfizzBuzzes = map fizzBuzz [1..100]...
module Main wheremain :: IO ()main = doputStrLn "Printing FizzBuzzes..."print fizzBuzzesfizzBuzzes = map fizzBuzz [1..100]...
module Main wheremain :: IO ()main = doputStrLn "Printing FizzBuzzes..."print fizzBuzzesfizzBuzzes = map fizzBuzz [1..100]...
putStr :: String -> IO ()putStrLn :: String -> IO ()getLine :: IO StringВвод-вывод. Монада IOgetName :: IO ()getName = dop...
getName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")Ввод...
getName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")Ввод...
Ввод-вывод. Монада IOgetName :: IO StringgetName = doputStrLn "What is your name?"getLinewriteMyName :: IO ()writeMyName =...
Ввод-вывод. Монада IOgetName :: IO StringgetName = doputStrLn "What is your name?"getLinewriteMyName :: IO ()writeMyName =...
data Bool = True| FalseАлгебраический тип данныхBool
Алгебраический тип данныхBooldata Bool = True| FalseКонструктор типаКонструкторызначений
Алгебраический тип данныхBooldata Bool = True| Falsefact n = case n == 0 ofTrue -> 1False -> fact (n-1) * nisHaskellGreat ...
Перечисленияdata Color = Red| Green| Blue| Yellow| Orange| Black| White
Алгебраические типы данныхdata STree a= Tip| Node (STree a) a (STree a)53 71 4
data STree a= Tip| Node (STree a) a (STree a)Алгебраические типы данныхПеременная типа3 поля53 71 4
data STree a= Tip| Node (STree a) a (STree a)type IntSTree = STree IntАлгебраические типы данных53 71 4
Алгебраические типы данныхmyTree, left, right :: IntSTreemyTree = Node left 5 rightleft = Node subLeft 3 subRightright = N...
Сопоставление с образцомheight :: IntSTree -> Intheight Tip = 0height (Node left _ right) = 1 + subHeightwheresubHeight = ...
КортежиnodeWeight :: IntSTree -> (Int, Int)nodeWeight Tip = (0, 0)nodeWeight (Node l val r) = let(_, lWeight) = nodeWeight...
Модулиmodule MyLibrary.MyMap whereimport Data.Listimport Prelude hiding (map, (++))import qualified Data.Map as MapmyMap =...
Модуль Prelude(&&), (||) :: Bool -> Bool -> Boolnot :: Bool -> Boolmax, min :: a -> a -> aputStr, putStrLn :: String -> IO...
Полезные библиотеки● Data.ByteString● Data.Text● Data.List● Data.Map● Data.Array● Data.Maybe● Time● System.Random● Control...
Инструменты разработки
Haskell Platform● Компилятор GHC● Интерпретатор GHCi● Базовые библиотеки● Пакетный менеджерCabal● Документирование -Haddoc...
Glasgow Haskell CompilerКомпиляция:ghc --make FizzBuzz.hsghc --make -O2 FizzBuzz.hsghc --make -O2 -threaded FizzBuzz.hsВып...
REPLReadEvalPrintLoop
GHCi(GHC interpreter)> fizzBuzz 1"1"> (3 + 30)33> fizzBuzz<interactive>:1:1:No instance for (Show (Int -> String))arising ...
GHCi(GHC interpreter)
Команды::t <expr> - тип выражения <expr>:r - перезагрузить код:m + <module> - подключить библиотеку:q - выход> :t mapmap :...
http://hackage.haskell.org/packages/hackage.htmlHackage - репозиторий библиотек
Cabal - пакетный менеджерУстановить пакет (библиотеку):cabal install <package>Обновить список пакетов:cabal updateРаспаков...
Информация по Haskell● Hackage● Haskell Wiki - Вики обо всем вокруг Haskell(http://www.haskell.org/haskellwiki/Haskell)● H...
IDE
EclipseFP
Leksah
SublimeHaskell
vim
emacs
Wantmore?
Haskell: средний уровень
Data.Maybephonebook :: [(String, String)]phonebook =[ ("Bob", "01788 665242"), ("Fred", "01624 556442"), ("Alice", "01889 ...
Data.Maybephonebook :: [(String, String)]lookup :: a -> [(a, b)] -> Maybe b
Data.Maybephonebook :: [(String, String)]lookup :: a -> [(a, b)] -> Maybe ba :: Stringb :: String
Data.Maybephonebook :: [(String, String)]lookup :: a -> [(a, b)] -> Maybe ba :: Stringb :: Stringdata Maybe a = Nothing| J...
Data.MaybegetPhone :: String -> Maybe StringgetPhone name = lookup name phonebook
Data.MaybegetPhone :: String -> Maybe StringgetPhone name = lookup name phonebookprintPhone :: Maybe String -> IO ()printP...
Data.MaybegetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...
Data.MaybegetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPhone = printPh...
Data.MaybegetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPhone = printPh...
Data.Eitherdata Maybe a = Nothing| Just adata Either a b = Left a| Right b
$ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPh...
$ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPh...
$ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPh...
$ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPh...
$ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPh...
$ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> I...
Бесточечный стильgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()sh...
Бесточечный стильgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()sh...
Бесточечный стильgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()sh...
Бесточечный стильgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()sh...
Бесточечный стильgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()sh...
Классы типов
Классы типовlookup :: a -> [(a, b)] -> Maybe b
Классы типовlookup :: Eq a => a -> [(a, b)] -> Maybe b
Классы типовlookup :: Eq a => a -> [(a, b)] -> Maybe b-- Prelude:class Eq a where(==), (/=) :: a -> a -> Bool
lookup :: Eq a => a -> [(a, b)] -> Maybe b-- Prelude:class Eq a where(==), (/=) :: a -> a -> Boolinstance Eq String wheres...
lookup :: Eq a => a -> [(a, b)] -> Maybe b-- Prelude:class Eq a where(==), (/=) :: a -> a -> Boolinstance Eq Char wherec1 ...
lookup :: Eq a => a -> [(a, b)] -> Maybe b-- Prelude:class Eq a where(==), (/=) :: a -> a -> Boolinstance Eq Int wherei1 =...
Класс типов Eqdata STree a= Tip| Node (STree a) a (STree a)compare :: STree Int -> STree Int -> Boolcompare t1 t2 = t1 == t2
Класс типов Eqdata STree a= Tip| Node (STree a) a (STree a)compare :: STree Int -> STree Int -> Boolcompare t1 t2 = t1 == t2
No instance for (Eq (STree Int))arising from a use of ==Possible fix: add an instance declaration for (Eq (STree Int))In t...
Класс типов Eqdata STree a= Tip| Node (STree a) a (STree a)deriving (Eq)compare :: STree Int -> STree Int -> Boolcompare t...
Класс типов Eqdata STree a= Tip| Node (STree a) a (STree a)deriving (Eq)compare :: STree Int -> STree Int -> Boolcompare t...
Класс типов Eqinstance Eq a => Eq (STree a ) whereTip == Tip = TrueTip == (Node _ _ _) = False(Node _ _ _) == Tip = False(...
Класс типов Eqinstance Eq a => Eq (STree a ) whereTip == Tip = TrueTip == (Node _ _ _) = False(Node _ _ _) == Tip = False(...
Класс типов Eqinstance Eq a => Eq (STree a ) whereTip == Tip = TrueTip == (Node _ _ _) = False(Node _ _ _) == Tip = False(...
Классы типов Show, Readdata STree a= Tip| Node (STree a) a (STree a)deriving (Eq, Show, Read)
Классы типов Show, Readdata STree a= Tip| Node (STree a) a (STree a)deriving (Eq, Show, Read)main = dolet strTree = show m...
Классы типов Show, Readdata STree a= Tip| Node (STree a) a (STree a)deriving (Eq, Show, Read)main = dolet strTree = show m...
Генераторы списков(c) Miran Lipovača http://learnyouahaskell.com/
1. На множестве от 1 до 100.Cоздать список [x]:list1 = [1..100]list2 = [x | x <- [1..100]]
Cоздать список [x]:list1 = [1, 3..100]list2 = [x | x <- [1..100], odd x]1. На множестве от 1 до 100.2. Только нечетные.
Cоздать список [x]:1. На множестве от 1 до 100.2. Только нечетные.3. Делящиеся на 3 без остатка.list1 = [3, 9..100]list2 =...
Cоздать список [x]:1. На множестве от 1 до 100.2. Только нечетные.3. Делящиеся на 3 без остатка.4. Делящиеся на 7 без оста...
1. x - от 1 до 100, y - от 100 до 200.2. x - четные, y - нечетные.3. x + y < 200.4. |x - y| > 190.Cоздать список [(x, y)]:...
Основы монад
Монада IO
Отправной примерlet rndGen1 = mkStdGen 100
Отправной примерlet rndGen1 = mkStdGen 100let (val1, rndGen2) = random rndGen1
Отправной примерlet rndGen1 = mkStdGen 100let (val1, rndGen2) = random rndGen1let (val2, rndGen3) = random rndGen2
let world0 = getWorldgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn ...
let world0 = getWorldlet (val1, world1) = ioAction1 world0getName :: IO ()getName = doputStrLn "What is your name?"yourNam...
let world0 = getWorldlet (val1, world1) = ioAction1 world0let (val2, world2) = ioAction2 world1getName :: IO ()getName = d...
Стратегия связывания, IOworld0 = getWorld((), world1)(yourName, world2)((), world3)((), world4)getName :: IO ()getName = d...
do-нотацияgetName =putStrLn "What is your name?"getName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLi...
do-нотацияgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName +...
do-нотацияgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName +...
do-нотацияgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName +...
do-нотацияgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName +...
Возвращаемое значениеgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn ...
Возвращаемое значениеgetName :: IO StringgetName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putSt...
Возвращаемое значениеgetName :: IO StringgetName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putSt...
Монада Statenewtype State s a = State{runState :: s -> (a, s)}
Монада Statenewtype State s a = State{runState :: s -> (a, s)}
Монада StatemyFunc :: State Int IntmyFunc = doval <- getput (val - 8)getgetNumber = evalState myFunc 50main = print getNum...
Монада StatemyFunc :: State Int IntmyFunc = doval <- getput (val - 8)getgetNumber = evalState myFunc 50main = print getNum...
Стратегия связывания, Statelet state1 = evalState 50let (val1, state2) = get state1let ((), state3) = put (val1 - 8) state...
Parsec
Пример: парсинг intparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)test :: Either P...
Пример: парсинг intparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)test :: Either P...
Пример: парсинг intparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)test :: Either P...
Пример: парсинг intparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)test :: Either P...
Пример: парсинг intparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)test :: Either P...
Пример: парсинг inttest :: Either ParseError Inttest = parse parseInt [] " 10"> testRight 10
Пример: парсинг inttest2 :: Either ParseError Inttest2 = parse parseInt [] "AAA"> test2Left (line 1, column1):unexpected "...
Символьные парсерыspace :: ParsecT s u m Charspaces :: ParsecT s u m ()alphaNum :: ParsecT s u m Charletter :: ParsecT s u...
Комбинаторы парсеровmany1 :: ParsecT s u m a -> ParsecT s u m [a]many :: ParsecT s u m a -> ParsecT s u m [a]count :: Int ...
parseName :: GenParser Char st StringparseName = dospacesfirst <- upperrest <- many letterreturn (first : rest)> parse par...
Кастомные парсерыparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)parseName :: GenPa...
Кастомные парсерыparsePerson :: GenParser Char st(String, Int, String)parsePerson = doname <- parseNameage <- parseIntzodi...
Кастомные парсерыparsePerson :: GenParser Char st(String, Int, String)parsePerson = doname <- parseNameage <- parseIntzodi...
Связь с БНФint ::= many1 digitstring ::= many1 charname ::= upper stringperson ::= name integer nameparsePerson :: GenPars...
Парсинг в ASTdata Person = Person{ name :: String, age :: Int, zodiac :: String }parsePerson :: GenParser Char st (Person ...
Вывод ошибки:комбинатор <?>parsePerson :: GenParser Char st (Person String Int String)parsePerson = doname <- parseName <?...
Вывод ошибки:комбинатор <?>parsePerson :: GenParser Char st (Person String Int String)parsePerson = doname <- parseName <?...
Person.xml<?xml version="1.0" encoding="UTF-8" ?><Person Age="20" Name="Bob"><Zodiac>Lion</Zodiac></Person>
XmlGen - генерация XMLwritePerson :: Person -> Xml ElemwritePerson (Person name age zodiac) = letattribs = xattr "Name" na...
HaXml - парсинг XMLreadPersonXml = docontent <- readFile "Person.xml"let (Document _ _ root _) = xmlParse "error.log" cont...
Domain specific languages
Зачем нужны DSL?Построение DSL длязадачи тождественнорешению задачи.
Какие бывают?● Внутренние● Внешние
DSL: Lambda The GatheringfDbl :: [Maybe Function] -> GS (Maybe Function)fDbl (Just (FValue x):[]) = return $ Just $ FValue...
AST, основанное на ADTefm := ExactFileMatching 2 0".EfmFunctionalTestDbtest2.db"cat1 : "CAT1" = Category [cat2] NoMatchcat...
AST, основанное на ADTdata DslTokenName = DslTokenName Stringdata DslTokenBody = DslGuardedBody{ dtbDslAdt :: DslAdt, dtbD...
Немного хардкора
Класс типов Monadclass Monad m where(>>=) :: m a -> (a -> m b) -> m b(>>) :: m a -> m b -> m breturn :: a -> m a
Зачем это надо?Монада 2Монада 1
Зачем это надо?Монада 2Монада 1
State + IOdata GS = GS { worldMap :: [Location], currentLocation :: Location, welded :: Bool, bucketFull :: Bool }deriving...
State + IOrun :: GameState Resultrun = dot <- get-- read a command from the userio . putStr $ "> "io . hFlush $ stdoutline...
HaskellScalaClojure...Want more?PLUGIN!!!
Haskell - huge presentation for DevDay about Haskell language
Upcoming SlideShare
Loading in …5
×

Haskell - huge presentation for DevDay about Haskell language

918 views
798 views

Published on

Huge version of presentation about Haskell programming language.

Published in: Technology, Education
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
918
On SlideShare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Haskell - huge presentation for DevDay about Haskell language

  1. 1. Haskell*Александр Гранинgraninas@gmail.com*alpha version of presentation
  2. 2. HaskellScalaClojure...Want more????
  3. 3. О чем доклад?● Часть 1. Ликбез по ФП и Haskell○ Функциональное программирование○ Язык Haskell. Применимость языка○ Язык Haskell. Основы○ Инструменты разработчика● Часть 2. Haskell: средний уровень○ Язык Haskell: We need to go deeper○ Полезные библиотеки○ DSL○ Разбор реальной программы● Часть 3. Немного хардкора
  4. 4. Программирование:● Императивное● Объектно-ориентированное● Функциональное● Логическое● Декларативное
  5. 5. Задача:обратить слова в строкеThis is a end, my only friend!friend! only my end, the is This
  6. 6. Императивные языки
  7. 7. 1. std::string words = "This is the end, myonly friend!";2. std::vector<std::string> swv;3. boost::split(swv, words, boost::is_any_of(" "));4. std::reverse(swv.begin(), swv.end());5. std::string newwords = (std::for_each(swv.begin(), swv.end(),StringTAndJ())).value();Программирование в терминахпоследовательных операций
  8. 8. Объектно -ориентированные языки
  9. 9. Программирование в терминахвзаимодействия объектов1. List<String> ls = Arrays.asList("This is theend, my only friend!".split("s"));2. Collections.reverse(ls);3. StringBuilder sb = new StringBuilder(32);4. for (String s : ls)5. sb.append(" ").append(s);6. String reversed = sb.toString().trim()
  10. 10. Функциональные языки
  11. 11. Программирование в терминахтрансформации данныхunwords . reverse . words$ "This is the end, my only friend!"...Еще один пример..."This is the end, my only friend!".split(" ").reverse.reduceLeft( (x,y) => x+ +y )
  12. 12. (println "Hello World!")printfn "Hello World!"io:format("Hello, World!~n").putStrLn "Hello World!"println("Hello World!")
  13. 13. Функциональноепрограммирование● ...● ...● ...● ...● ...● ...?
  14. 14. Функциональноепрограммированиеfactorial n =if (n == 0)then 1else (n * factorial (n-1))ten = 10● Все есть функция● ...● ...● ...● ...● ...
  15. 15. Функциональноепрограммированиеfib 0 = 0fib 1 = 1fib n = fib (n-1) + fib (n-2)● Все есть функция● Рекурсия● ...● ...● ...● ...
  16. 16. ФункциональноепрограммированиеnumberList = [1, 2, 3, 4, 5]modifyList func list = map func listsquare x = x * xdouble x = 2 * xzero x = 0squares = modifyList square numberListdoubles = modifyList double numberListzeros = modifyList zero numberList● Все есть функция● Рекурсия● Функции высшихпорядков● ...● ...● ...
  17. 17. Функциональноепрограммированиеa := 1a := 2DO NOT CHANGE!The immutability is with you● Все есть функция● Рекурсия● Функции высшихпорядков● Иммутабельностьданных● ...● ...
  18. 18. Функциональноепрограммирование● Все есть функция● Рекурсия● Функции высшихпорядков● Иммутабельностьданных● Чистые функции● ...
  19. 19. ФункциональноепрограммированиеfizzBuzz :: Int -> StringfizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xwhereisDivided x n = (x `mod` n) == 0main :: IO ()main = mapM_ (putStrLn . fizzBuzz) [1..100]● Все есть функция● Рекурсия● Функции высшихпорядков● Иммутабельностьданных● Чистые функции● Нет побочныхэффектов
  20. 20. Язык HaskellHaskell - это...● ...● ...● ...● ...● ...● ...● ...?
  21. 21. Язык HaskellHaskell - это...● Чистый функциональный,● строго статически типизированный,● кроссплатформенный,● компилируемый язык● общего назначения● с ленивой семантикой● и автоматическим выводом типов.
  22. 22. Краткая история Haskell● Хаскель Карри● Саймон Пейтон Джонс● Семейство языков ML● Прародитель - Miranda● 1990 год - Haskell 1.0● 1998 год - Haskell 98● 2009 год - Haskell 2010«Доказательство —это программа, адоказываемаяформула — это типпрограммы»(c)MiranLipovača
  23. 23. Слабые стороны Haskell● Системное программирование● Real-time системы● Сложные системы со множествомпобочных эффектов● GUI
  24. 24. Сильные стороны Haskell● Обработка данных● Надежность и выразительность кода● Алгоритмика● Автоматическая и ручнаяпараллелизация● Большие объемы данных● DSL● Парсинг● Сложные вычисления● Вспомогательные инструменты
  25. 25. FUNctionIts all Haskell is about
  26. 26. Success Stories?
  27. 27. Success StoriesAbstract Syntax TreeCode baseLex-pass
  28. 28. Success Stories● HaLVM● HaLFS● Copilot● Orc● ...
  29. 29. Success Stories
  30. 30. Success Stories
  31. 31. Success StoriesNgnTraffic
  32. 32. Success StoriesWantmore?http://www.haskell.org/haskellwiki/Haskell_in_industry
  33. 33. Haskell и популярность?
  34. 34. Haskell - не мэйнстрим?..
  35. 35. Haskell - не мэйнстрим?..
  36. 36. В России - не мэйнстрим...● Общее оставание развития - 20 лет● Низкое качество преподавания● Консервативный менталитет "зубров"● Инакомыслие преследуется и порицается● Нежелание изучать нестандартное● Страх перед неизвестным● Мифы и стереотипы
  37. 37. Язык Haskell: Основы
  38. 38. Пара простых примеров
  39. 39. Числа Фибоначчиfib 0 = 0fib 1 = 1fib n = fib (n-1) + fib (n-2)
  40. 40. Сопоставление с образцомfib 0 = 0fib 1 = 1fib n = fib (n-1) + fib (n-2)
  41. 41. Факториалfact 0 = 1fact n = fact (n-1) * n
  42. 42. fact 0 = 1fact n = fact (n-1) * nСопоставление с образцом
  43. 43. Задача: FizzBuzzНапишите программу,которая выводит на экранчисла от 1 до 100.При этом вместо чисел,кратных трем, программадолжна выводить слово«Fizz», а вместо чисел,кратных пяти — слово«Buzz». Если число кратнои 3, и 5, то программадолжна выводить слово«FizzBuzz»1. 12. 23. Fizz4. 45. Buzz6. Fizz7. 78. 89. Fizz10. Buzz11. 1112. Fizz13. 1314. 1415. FizzBuzz16. 1617. 1718. Fizz
  44. 44. -- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided x n = (x `mod` n) == 0
  45. 45. -- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided x n = (x `mod` n) == 0> fizzBuzz 1"1"> fizzBuzz 30"FizzBuzz"
  46. 46. > fizzBuzz 1"1"> fizzBuzz 30"FizzBuzz"-- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided x n = (x `mod` n) == 0Телафункции
  47. 47. -- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided x n = (x `mod` n) == 0Guards(Охранныевыражения)
  48. 48. -- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided x n = (x `mod` n) == 0Bool functioncallBoolexpression
  49. 49. -- File FizzBuzz.hs:module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided x n = (x `mod` n) == 0Default case,"в противномслучае"
  50. 50. module Main wherefizzBuzz x = if isDivided x 15then "FizzBuzz"else if isDivided x 5then "Buzz"else if isDivided x 3then "Fizz"else show x
  51. 51. module Main wherefizzBuzz x = case isDivided x 15 ofTrue -> "FizzBuzz"False -> case isDivided x 5 ofTrue -> "Buzz"False -> case isDivided x 3 ofTrue -> "Fizz"False -> show x
  52. 52. module Main wherefizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided x n = (x `mod` n) == 0
  53. 53. module Main wherefizzBuzz :: Int -> StringfizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0
  54. 54. module Main wherefizzBuzz :: Int -> StringfizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0Декларациятипа функцииДекларациятипа функции
  55. 55. Декларация типаfunc :: Int -> Int -> Bool1 2РезультатТип: Аргумент Аргумент3
  56. 56. module Main wherefizzBuzz :: Int -> StringfizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0fizzBuzzes :: [String]fizzBuzzes = map fizzBuzz [1..100]
  57. 57. module Main wherefizzBuzz :: Int -> StringfizzBuzz x | isDivided x 15 = "FizzBuzz"| isDivided x 5 = "Buzz"| isDivided x 3 = "Fizz"| otherwise = show xisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0fizzBuzzes :: [String]fizzBuzzes = map fizzBuzz [1..100]Тип: список изстрокСписок [Int]:от 1 до 100
  58. 58. Функции высших порядковfizzBuzz :: Int -> StringfizzBuzzes :: [String]fizzBuzzes = map fizzBuzz [1..100]
  59. 59. Функции высших порядковfizzBuzz :: Int -> StringfizzBuzzes :: [String]fizzBuzzes = map fizzBuzz [1..100]map :: (a -> b) -> [a] -> [b]
  60. 60. Функции высших порядковmap :: (a -> b) -> [a] -> [b]fizzBuzz :: Int -> StringfizzBuzzes :: [String]fizzBuzzes = map fizzBuzz [1..100]
  61. 61. Полиморфизмmap :: (a -> b) -> [a] -> [b]a :: Intb :: StringfizzBuzz :: Int -> StringfizzBuzzes :: [String]fizzBuzzes = map fizzBuzz [1..100]
  62. 62. ЛямбдыisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0
  63. 63. ЛямбдыisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0isDivided :: Int -> (Int -> Bool)isDivided x = n -> (x `mod` n) == 0
  64. 64. ЛямбдыisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0isDivided :: Int -> (Int -> Bool)isDivided x = n -> (x `mod` n) == 0isDivided :: (Int -> Int -> Bool)isDivided = x n -> (x `mod` n) == 0
  65. 65. ЛямбдыisDivided :: Int -> Int -> BoolisDivided x n = (x `mod` n) == 0isDivided :: Int -> (Int -> Bool)isDivided x = n -> (x `mod` n) == 0isDivided :: (Int -> Int -> Bool)isDivided = x n -> (x `mod` n) == 0
  66. 66. Лямбдыx n -> (x `mod` n) == 0
  67. 67. Лямбдыx n -> (x `mod` n) == 0Аргументы Тело функции
  68. 68. module Main wheremain :: IO ()main = doputStrLn "Printing FizzBuzzes..."print fizzBuzzesfizzBuzzes = map fizzBuzz [1..100]...Модуль Main. Функция main
  69. 69. module Main wheremain :: IO ()main = doputStrLn "Printing FizzBuzzes..."print fizzBuzzesfizzBuzzes = map fizzBuzz [1..100]...Модуль Main. Функция mainМонада IO
  70. 70. module Main wheremain :: IO ()main = doputStrLn "Printing FizzBuzzes..."print fizzBuzzesfizzBuzzes = map fizzBuzz [1..100]...Ввод-вывод. Монада IOМонадическиевычисления
  71. 71. putStr :: String -> IO ()putStrLn :: String -> IO ()getLine :: IO StringВвод-вывод. Монада IOgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")
  72. 72. getName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")Ввод-вывод. Монада IOputStr :: String -> IO ()putStrLn :: String -> IO ()getLine :: IO String
  73. 73. getName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")Ввод-вывод. Монада IOyourName :: StringputStr :: String -> IO ()putStrLn :: String -> IO ()getLine :: IO String
  74. 74. Ввод-вывод. Монада IOgetName :: IO StringgetName = doputStrLn "What is your name?"getLinewriteMyName :: IO ()writeMyName = doname <- getNamewriteFile "myName.txt" name
  75. 75. Ввод-вывод. Монада IOgetName :: IO StringgetName = doputStrLn "What is your name?"getLinewriteMyName :: IO ()writeMyName = doname <- getNamewriteFile "myName.txt" namewriteFile :: FilePath -> String -> IO ()
  76. 76. data Bool = True| FalseАлгебраический тип данныхBool
  77. 77. Алгебраический тип данныхBooldata Bool = True| FalseКонструктор типаКонструкторызначений
  78. 78. Алгебраический тип данныхBooldata Bool = True| Falsefact n = case n == 0 ofTrue -> 1False -> fact (n-1) * nisHaskellGreat :: BoolisHaskellGreat = True
  79. 79. Перечисленияdata Color = Red| Green| Blue| Yellow| Orange| Black| White
  80. 80. Алгебраические типы данныхdata STree a= Tip| Node (STree a) a (STree a)53 71 4
  81. 81. data STree a= Tip| Node (STree a) a (STree a)Алгебраические типы данныхПеременная типа3 поля53 71 4
  82. 82. data STree a= Tip| Node (STree a) a (STree a)type IntSTree = STree IntАлгебраические типы данных53 71 4
  83. 83. Алгебраические типы данныхmyTree, left, right :: IntSTreemyTree = Node left 5 rightleft = Node subLeft 3 subRightright = Node Tip 7 TipsubLeft, subRight :: IntSTreesubLeft = Node Tip 1 TipsubRight = Node Tip 4 Tip53 71 4
  84. 84. Сопоставление с образцомheight :: IntSTree -> Intheight Tip = 0height (Node left _ right) = 1 + subHeightwheresubHeight = max (height left)(height right) 53 71 4
  85. 85. КортежиnodeWeight :: IntSTree -> (Int, Int)nodeWeight Tip = (0, 0)nodeWeight (Node l val r) = let(_, lWeight) = nodeWeight l(_, rWeight) = nodeWeight rin (val, val + lWeight + rWeight)> nodeWeight myTree(5, 20)53 71 4
  86. 86. Модулиmodule MyLibrary.MyMap whereimport Data.Listimport Prelude hiding (map, (++))import qualified Data.Map as MapmyMap = Map.fromList[ ("ABC", 1), ("BCD", 2), ("CDE", 3) ]
  87. 87. Модуль Prelude(&&), (||) :: Bool -> Bool -> Boolnot :: Bool -> Boolmax, min :: a -> a -> aputStr, putStrLn :: String -> IO ()getLine :: IO Stringmap :: (a -> b) -> [a] -> [b](++) :: [a] -> [a] -> [a]
  88. 88. Полезные библиотеки● Data.ByteString● Data.Text● Data.List● Data.Map● Data.Array● Data.Maybe● Time● System.Random● Control.Concurrent● Control.Monad
  89. 89. Инструменты разработки
  90. 90. Haskell Platform● Компилятор GHC● Интерпретатор GHCi● Базовые библиотеки● Пакетный менеджерCabal● Документирование -Haddock● MinGW (Windows) http://www.haskell.org/platform/
  91. 91. Glasgow Haskell CompilerКомпиляция:ghc --make FizzBuzz.hsghc --make -O2 FizzBuzz.hsghc --make -O2 -threaded FizzBuzz.hsВыполнение:runghc FizzBuzz.hs
  92. 92. REPLReadEvalPrintLoop
  93. 93. GHCi(GHC interpreter)> fizzBuzz 1"1"> (3 + 30)33> fizzBuzz<interactive>:1:1:No instance for (Show (Int -> String))arising from a use of printPossible fix:add an instance declaration for (Show (Int -> String))In a stmt of an interactive GHCi command: print it
  94. 94. GHCi(GHC interpreter)
  95. 95. Команды::t <expr> - тип выражения <expr>:r - перезагрузить код:m + <module> - подключить библиотеку:q - выход> :t mapmap :: (a -> b) -> [a] -> [b]> :t map (+1) [1..5]map (+1) [1..5] :: (Num b, Enum b) => [b]GHCi(GHC interpreter)
  96. 96. http://hackage.haskell.org/packages/hackage.htmlHackage - репозиторий библиотек
  97. 97. Cabal - пакетный менеджерУстановить пакет (библиотеку):cabal install <package>Обновить список пакетов:cabal updateРаспаковать пакет в локальную папку:cabal unpack <package>
  98. 98. Информация по Haskell● Hackage● Haskell Wiki - Вики обо всем вокруг Haskell(http://www.haskell.org/haskellwiki/Haskell)● Hoogle - Поисковая система по документации(http://www.haskell.org/hoogle/)● Haskell Cafe - Списки рассылки(http://www.haskell.org/mailman/listinfo/haskell-cafe)● StackOverflow - Много полезной информации(http://stackoverflow.com/questions/tagged/haskell)
  99. 99. IDE
  100. 100. EclipseFP
  101. 101. Leksah
  102. 102. SublimeHaskell
  103. 103. vim
  104. 104. emacs
  105. 105. Wantmore?
  106. 106. Haskell: средний уровень
  107. 107. Data.Maybephonebook :: [(String, String)]phonebook =[ ("Bob", "01788 665242"), ("Fred", "01624 556442"), ("Alice", "01889 985333"), ("Jane", "01732 187565") ]
  108. 108. Data.Maybephonebook :: [(String, String)]lookup :: a -> [(a, b)] -> Maybe b
  109. 109. Data.Maybephonebook :: [(String, String)]lookup :: a -> [(a, b)] -> Maybe ba :: Stringb :: String
  110. 110. Data.Maybephonebook :: [(String, String)]lookup :: a -> [(a, b)] -> Maybe ba :: Stringb :: Stringdata Maybe a = Nothing| Just a
  111. 111. Data.MaybegetPhone :: String -> Maybe StringgetPhone name = lookup name phonebook
  112. 112. Data.MaybegetPhone :: String -> Maybe StringgetPhone name = lookup name phonebookprintPhone :: Maybe String -> IO ()printPhone Nothing = putStrLn "Not found."printPhone (Just phone) = putStrLn phone
  113. 113. Data.MaybegetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...
  114. 114. Data.MaybegetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPhone = printPhone (getPhone "Alice")
  115. 115. Data.MaybegetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPhone = printPhone (getPhone "Alice")> showPhone01889 985333
  116. 116. Data.Eitherdata Maybe a = Nothing| Just adata Either a b = Left a| Right b
  117. 117. $ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPhone = printPhone (getPhone "Alice")> showPhone01889 985333
  118. 118. $ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPhone = printPhone $ getPhone "Alice"> showPhone01889 985333
  119. 119. $ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPhone = printPhone $ getPhone "Alice"Application
  120. 120. $ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPhone = printPhone $ getPhone ("Alice")Application
  121. 121. $ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: IO ()showPhone = printPhone $ getPhone $ "Alice"
  122. 122. $ - оператор примененияgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()showPhone name = printPhone $ getPhone name
  123. 123. Бесточечный стильgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()showPhone name = (printPhone . getPhone) name
  124. 124. Бесточечный стильgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()showPhone name = (printPhone . getPhone) nameprintPhone . getPhone :: String -> IO ()
  125. 125. Бесточечный стильgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()showPhone name = (printPhone . getPhone) name
  126. 126. Бесточечный стильgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()showPhone = printPhone . getPhone
  127. 127. Бесточечный стильgetPhone :: String -> Maybe String...printPhone :: Maybe String -> IO ()...showPhone :: String -> IO ()showPhone = printPhone . getPhonePointfree style
  128. 128. Классы типов
  129. 129. Классы типовlookup :: a -> [(a, b)] -> Maybe b
  130. 130. Классы типовlookup :: Eq a => a -> [(a, b)] -> Maybe b
  131. 131. Классы типовlookup :: Eq a => a -> [(a, b)] -> Maybe b-- Prelude:class Eq a where(==), (/=) :: a -> a -> Bool
  132. 132. lookup :: Eq a => a -> [(a, b)] -> Maybe b-- Prelude:class Eq a where(==), (/=) :: a -> a -> Boolinstance Eq String wheres1 == s2 = ... -- compare stringss1 /= s2 = not (s1 == s2)Классы типов
  133. 133. lookup :: Eq a => a -> [(a, b)] -> Maybe b-- Prelude:class Eq a where(==), (/=) :: a -> a -> Boolinstance Eq Char wherec1 == c2 = ... -- compare charsc1 /= c2 = not (c1 == c2)Классы типов
  134. 134. lookup :: Eq a => a -> [(a, b)] -> Maybe b-- Prelude:class Eq a where(==), (/=) :: a -> a -> Boolinstance Eq Int wherei1 == i2 = ... -- compare intsi1 /= i2 = not (i1 == i2)Классы типов
  135. 135. Класс типов Eqdata STree a= Tip| Node (STree a) a (STree a)compare :: STree Int -> STree Int -> Boolcompare t1 t2 = t1 == t2
  136. 136. Класс типов Eqdata STree a= Tip| Node (STree a) a (STree a)compare :: STree Int -> STree Int -> Boolcompare t1 t2 = t1 == t2
  137. 137. No instance for (Eq (STree Int))arising from a use of ==Possible fix: add an instance declaration for (Eq (STree Int))In the expression: t1 == t2In an equation for compare: compare t1 t2 = t1 == t2Класс типов Eqdata STree a= Tip| Node (STree a) a (STree a)compare :: STree Int -> STree Int -> Boolcompare t1 t2 = t1 == t2
  138. 138. Класс типов Eqdata STree a= Tip| Node (STree a) a (STree a)deriving (Eq)compare :: STree Int -> STree Int -> Boolcompare t1 t2 = t1 == t2
  139. 139. Класс типов Eqdata STree a= Tip| Node (STree a) a (STree a)deriving (Eq)compare :: STree Int -> STree Int -> Boolcompare t1 t2 = t1 == t2
  140. 140. Класс типов Eqinstance Eq a => Eq (STree a ) whereTip == Tip = TrueTip == (Node _ _ _) = False(Node _ _ _) == Tip = False(Node l1 v1 r1) == (Node l2 v2 r2) = leteqL = l1 == l2eqR = r1 == r2eqV = v1 == v2in eqL && eqR && eqV
  141. 141. Класс типов Eqinstance Eq a => Eq (STree a ) whereTip == Tip = TrueTip == (Node _ _ _) = False(Node _ _ _) == Tip = False(Node l1 v1 r1) == (Node l2 v2 r2) = leteqL = l1 == l2eqR = r1 == r2eqV = v1 == v2in eqL && eqR && eqV
  142. 142. Класс типов Eqinstance Eq a => Eq (STree a ) whereTip == Tip = TrueTip == (Node _ _ _) = False(Node _ _ _) == Tip = False(Node l1 v1 r1) == (Node l2 v2 r2) = leteqL = l1 == l2eqR = r1 == r2eqV = v1 == v2in eqL && eqR && eqV
  143. 143. Классы типов Show, Readdata STree a= Tip| Node (STree a) a (STree a)deriving (Eq, Show, Read)
  144. 144. Классы типов Show, Readdata STree a= Tip| Node (STree a) a (STree a)deriving (Eq, Show, Read)main = dolet strTree = show myTreewriteFile "tree.txt" strTreefileContent <- readFile "tree.txt"let readedTree = read fileContentprint . height $ readedTree
  145. 145. Классы типов Show, Readdata STree a= Tip| Node (STree a) a (STree a)deriving (Eq, Show, Read)main = dolet strTree = show myTreewriteFile "tree.txt" strTreefileContent <- readFile "tree.txt"let readedTree = read fileContentprint . height $ readedTreestrTree :: StringreadedTree :: STree Int
  146. 146. Генераторы списков(c) Miran Lipovača http://learnyouahaskell.com/
  147. 147. 1. На множестве от 1 до 100.Cоздать список [x]:list1 = [1..100]list2 = [x | x <- [1..100]]
  148. 148. Cоздать список [x]:list1 = [1, 3..100]list2 = [x | x <- [1..100], odd x]1. На множестве от 1 до 100.2. Только нечетные.
  149. 149. Cоздать список [x]:1. На множестве от 1 до 100.2. Только нечетные.3. Делящиеся на 3 без остатка.list1 = [3, 9..100]list2 = [x | x <- [1..100], odd x,x `mod` 3 == 0]
  150. 150. Cоздать список [x]:1. На множестве от 1 до 100.2. Только нечетные.3. Делящиеся на 3 без остатка.4. Делящиеся на 7 без остатка.list1 = [21, 42..100]list2 = [x | x <- [1..100], odd x,x `mod` 3 == 0,x `mod` 7 == 0]
  151. 151. 1. x - от 1 до 100, y - от 100 до 200.2. x - четные, y - нечетные.3. x + y < 200.4. |x - y| > 190.Cоздать список [(x, y)]:list = [(x, y) | x <- [1..100], even x,y <- [100..200], odd y,x + y < 200,abs (x - y) > 190]
  152. 152. Основы монад
  153. 153. Монада IO
  154. 154. Отправной примерlet rndGen1 = mkStdGen 100
  155. 155. Отправной примерlet rndGen1 = mkStdGen 100let (val1, rndGen2) = random rndGen1
  156. 156. Отправной примерlet rndGen1 = mkStdGen 100let (val1, rndGen2) = random rndGen1let (val2, rndGen3) = random rndGen2
  157. 157. let world0 = getWorldgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")Стратегия связывания, IOworld0 = getWorld
  158. 158. let world0 = getWorldlet (val1, world1) = ioAction1 world0getName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")Стратегия связывания, IOworld0 = getWorld((), world1)
  159. 159. let world0 = getWorldlet (val1, world1) = ioAction1 world0let (val2, world2) = ioAction2 world1getName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")Стратегия связывания, IOworld0 = getWorld((), world1)(yourName, world2)
  160. 160. Стратегия связывания, IOworld0 = getWorld((), world1)(yourName, world2)((), world3)((), world4)getName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")let world0 = getWorldlet (val1, world1) = ioAction1 world0let (val2, world2) = ioAction2 world1
  161. 161. do-нотацияgetName =putStrLn "What is your name?"getName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")
  162. 162. do-нотацияgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")getName =putStrLn "What is your name?">>= _ -> getLine
  163. 163. do-нотацияgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")getName =putStrLn "What is your name?">>= _ -> getLine>>= yourName -> putStr "Hello, "
  164. 164. do-нотацияgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")getName =putStrLn "What is your name?">>= _ -> getLine>>= yourName -> putStr "Hello, ">>= _ -> putStrLn (yourName ++ "!")
  165. 165. do-нотацияgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")getName =putStrLn "What is your name?">> getLine>>= yourName -> putStr "Hello, ">> putStrLn (yourName ++ "!")
  166. 166. Возвращаемое значениеgetName :: IO ()getName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")
  167. 167. Возвращаемое значениеgetName :: IO StringgetName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")return yourNamereturn :: a -> m a
  168. 168. Возвращаемое значениеgetName :: IO StringgetName = doputStrLn "What is your name?"yourName <- getLineputStr "Hello, "putStrLn (yourName ++ "!")return yourNamereturn :: a -> m aa :: Stringm :: IO
  169. 169. Монада Statenewtype State s a = State{runState :: s -> (a, s)}
  170. 170. Монада Statenewtype State s a = State{runState :: s -> (a, s)}
  171. 171. Монада StatemyFunc :: State Int IntmyFunc = doval <- getput (val - 8)getgetNumber = evalState myFunc 50main = print getNumber
  172. 172. Монада StatemyFunc :: State Int IntmyFunc = doval <- getput (val - 8)getgetNumber = evalState myFunc 50main = print getNumber
  173. 173. Стратегия связывания, Statelet state1 = evalState 50let (val1, state2) = get state1let ((), state3) = put (val1 - 8) state2let (val2, state4) = get state3
  174. 174. Parsec
  175. 175. Пример: парсинг intparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)test :: Either ParseError Inttest = parse parseInt [] " 10"
  176. 176. Пример: парсинг intparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)test :: Either ParseError Inttest = parse parseInt [] " 10"
  177. 177. Пример: парсинг intparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)test :: Either ParseError Inttest = parse parseInt [] " 10"
  178. 178. Пример: парсинг intparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)test :: Either ParseError Inttest = parse parseInt [] " 10"
  179. 179. Пример: парсинг intparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)test :: Either ParseError Inttest = parse parseInt [] " 10"
  180. 180. Пример: парсинг inttest :: Either ParseError Inttest = parse parseInt [] " 10"> testRight 10
  181. 181. Пример: парсинг inttest2 :: Either ParseError Inttest2 = parse parseInt [] "AAA"> test2Left (line 1, column1):unexpected "A"expecting white space or digit
  182. 182. Символьные парсерыspace :: ParsecT s u m Charspaces :: ParsecT s u m ()alphaNum :: ParsecT s u m Charletter :: ParsecT s u m Chardigit :: ParsecT s u m Charstring :: String -> ParsecT s u m StringoneOf :: [Char] -> ParsecT s u m CharnoneOf :: [Char] -> ParsecT s u m Charupper :: ParsecT s u m Charlower :: ParsecT s u m Char
  183. 183. Комбинаторы парсеровmany1 :: ParsecT s u m a -> ParsecT s u m [a]many :: ParsecT s u m a -> ParsecT s u m [a]count :: Int -> ParsecT s u m a -> ParsecT s u m [a]choice :: [ParsecT s u m a] -> ParsecT s u m aoptional :: ParsecT s u m a -> ParsecT s u m ()lookAhead :: ParsecT s u m a -> ParsecT s u m a.........
  184. 184. parseName :: GenParser Char st StringparseName = dospacesfirst <- upperrest <- many letterreturn (first : rest)> parse parseName [] " Peter331155"Right "Peter"
  185. 185. Кастомные парсерыparseInt :: GenParser Char st IntparseInt = dospacesres <- many1 digitreturn (read res)parseName :: GenParser Char st StringparseName = dospacesfirst <- upperrest <- many letterreturn (first : rest)
  186. 186. Кастомные парсерыparsePerson :: GenParser Char st(String, Int, String)parsePerson = doname <- parseNameage <- parseIntzodiac <- parseNamereturn (name, age, zodiac)
  187. 187. Кастомные парсерыparsePerson :: GenParser Char st(String, Int, String)parsePerson = doname <- parseNameage <- parseIntzodiac <- parseNamereturn (name, age, zodiac)
  188. 188. Связь с БНФint ::= many1 digitstring ::= many1 charname ::= upper stringperson ::= name integer nameparsePerson :: GenParser Char st (String, Int, String)parsePerson = doname <- parseNameage <- parseIntzodiac <- parseNamereturn (name, age, zodiac)
  189. 189. Парсинг в ASTdata Person = Person{ name :: String, age :: Int, zodiac :: String }parsePerson :: GenParser Char st (Person String Int String)parsePerson = doname <- parseNameage <- parseIntzodiac <- parseNamereturn (Person name age zodiac)
  190. 190. Вывод ошибки:комбинатор <?>parsePerson :: GenParser Char st (Person String Int String)parsePerson = doname <- parseName <?> "Name"age <- parseInt <?> "Age"zodiac <- parseName <?> "Zodiac"return (Person name age zodiac)data Person = Person{ name :: String, age :: Int, zodiac :: String }
  191. 191. Вывод ошибки:комбинатор <?>parsePerson :: GenParser Char st (Person String Int String)parsePerson = doname <- parseName <?> "Name"age <- parseInt <?> "Age"zodiac <- parseName <?> "Zodiac"return (Person name age zodiac)> parse parsePerson [] "%:;%?;%*%*"Left (line1, column 1):unexpected "%"expecting Name
  192. 192. Person.xml<?xml version="1.0" encoding="UTF-8" ?><Person Age="20" Name="Bob"><Zodiac>Lion</Zodiac></Person>
  193. 193. XmlGen - генерация XMLwritePerson :: Person -> Xml ElemwritePerson (Person name age zodiac) = letattribs = xattr "Name" name<> xattr "Age" (show age)info = xelems [ xelem "Zodiac" zodiac ]in xelem "Person" ( attribs <#> info )writePersonXml :: IO ()writePersonXml = dolet person = Person "Bob" 20 "Lion"let xmlDom = writePerson personlet xmlStr = xrender $ doc defaultDocInfo xmlDomByteString.writeFile "Person.xml" xmlStr
  194. 194. HaXml - парсинг XMLreadPersonXml = docontent <- readFile "Person.xml"let (Document _ _ root _) = xmlParse "error.log" contentlet person = toPerson (CElem root noPos)print persontoPerson :: Content i -> PersontoPerson p = letname = singleAttribute p "Name" idage = singleAttribute p "Age" readStringzodiacF = tag "Person" /> tag "Zodiac"zodiac = concatMap txtContent (zodiacF p)in Person name age zodiac
  195. 195. Domain specific languages
  196. 196. Зачем нужны DSL?Построение DSL длязадачи тождественнорешению задачи.
  197. 197. Какие бывают?● Внутренние● Внешние
  198. 198. DSL: Lambda The GatheringfDbl :: [Maybe Function] -> GS (Maybe Function)fDbl (Just (FValue x):[]) = return $ Just $ FValue (x * 2)fDbl _ = return NothingfGet :: [Maybe Function] -> GS (Maybe Function)fGet (Just (FValue i):[]) = dogd <- MST.getreturn $ field i gd TruefGet _ = return NothingfPut :: [Maybe Function] -> GS (Maybe Function)fPut (_:[]) = dox <- fI []return x
  199. 199. AST, основанное на ADTefm := ExactFileMatching 2 0".EfmFunctionalTestDbtest2.db"cat1 : "CAT1" = Category [cat2] NoMatchcat2 : "CAT2" = Category [] NoMatchcat3 : "CAT3" = Category [cat3] NoMatchrule : "Confidential data" = Rule Permit [] | id(n_of 1 (Evaluate [efm]) ([cat0]))
  200. 200. AST, основанное на ADTdata DslTokenName = DslTokenName Stringdata DslTokenBody = DslGuardedBody{ dtbDslAdt :: DslAdt, dtbDslExpression :: DslExpression }| DslNonGuardedBody{ dtbDslAdt :: DslAdt }data DslToken = EmptyDslToken| DslToken { dtDslTokenType :: DslTokenType, dtDslTokenName :: DslTokenName, dtDslTokenDescr :: DslTokenDescr, dtDslTokenBody :: DslTokenBody }
  201. 201. Немного хардкора
  202. 202. Класс типов Monadclass Monad m where(>>=) :: m a -> (a -> m b) -> m b(>>) :: m a -> m b -> m breturn :: a -> m a
  203. 203. Зачем это надо?Монада 2Монада 1
  204. 204. Зачем это надо?Монада 2Монада 1
  205. 205. State + IOdata GS = GS { worldMap :: [Location], currentLocation :: Location, welded :: Bool, bucketFull :: Bool }deriving (Show)newtype GameState a = GameState{ runGameState :: StateT GS IO a }
  206. 206. State + IOrun :: GameState Resultrun = dot <- get-- read a command from the userio . putStr $ "> "io . hFlush $ stdoutline <- io getLineresult <- case parseCommand line ofNothing -> write "Invalid command!" >> continueJust cmd -> do...........
  207. 207. HaskellScalaClojure...Want more?PLUGIN!!!

×