From c48c6b3660bd9b1429acba58cb5198a8ec08411d Mon Sep 17 00:00:00 2001 From: gcnew Date: Sat, 12 Nov 2016 13:55:33 +0200 Subject: [PATCH] Added new Readme, a homewrok exercice and other improvements --- README.md | 24 +- exercises/colorize/Colorize.md | 3 + exercises/list-comp/listcomp.hs | 31 ++ exercises/list-comp/listcomp.md | 28 ++ exercises/lists/Lists.md | 13 - exercises/lists/ListsHW.md | 10 + exercises/permutations/perm.hs | 7 + exercises/permutations/perm.md | 21 + exercises/secret-lang/Secret-lang.md | 13 +- lectures/{Readme.md => 00-setup/extra.md} | 0 lectures/00-setup/setup.md | 6 +- lectures/01-intro/intro.md | 12 +- .../02-syntax-and-types/syntax-and-types.md | 365 ++++++++++++++++++ .../linked-list.png | Bin .../lists-guards-patterns.md} | 353 +---------------- .../lcomprehension.md | 34 +- .../let-where.md | 0 .../poly.md | 42 +- 18 files changed, 548 insertions(+), 414 deletions(-) create mode 100644 exercises/list-comp/listcomp.hs create mode 100644 exercises/list-comp/listcomp.md create mode 100644 exercises/lists/ListsHW.md create mode 100644 exercises/permutations/perm.hs create mode 100644 exercises/permutations/perm.md rename lectures/{Readme.md => 00-setup/extra.md} (100%) create mode 100755 lectures/02-syntax-and-types/syntax-and-types.md rename lectures/{02-basics => 03-lists-guards-patterns}/linked-list.png (100%) rename lectures/{02-basics/basics.md => 03-lists-guards-patterns/lists-guards-patterns.md} (54%) mode change 100755 => 100644 rename lectures/{03-polymorphism => 04-list-comprehension}/lcomprehension.md (88%) rename lectures/{04-let-where => 05-polymorphism-let-where}/let-where.md (100%) rename lectures/{03-polymorphism => 05-polymorphism-let-where}/poly.md (94%) diff --git a/README.md b/README.md index ebf7a46..e4a990a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,24 @@ -Домашно №2 -==== +- **Седмица 1 (19.10.2016)** +[Относно курса](lectures/00-setup/setup.md) +[Що е то функционално програмиране? История на Haskell](lectures/01-intro/intro.md) +[Въведение в Haskell. Основени типове и синтаксис.](lectures/02-syntax-and-types/syntax-and-types.md) -**ВАЖНО:** Вижте [lists](./exercises/lists/Lists.md) за Домашно №2 +- **Седмица 2 (26.10.2016)** +[Въведение част 2 Lists, Guards and Pattern matching](lectures/03-lists-guards-patterns/lists-guards-patterns.md) +Домашно: [Езика на разбойниците](exercises/secret-lang/Secret-lang.md) ([secret-lang](exercises/secret-lang)) + +- **Седмица 3 (02.11.2016)** +[Работа със списъци](exercises/lists/Lists.md) +Задачи от часа: [Lists.hs](exercises/lists/Lists.hs), [Colorize](exercises/colorize/Colorize.md) ([colorize](exercises/colorize)) +Домашно: [Домашно Lists](exercises/lists/ListsHW.md) ([lists](exercises/lists)) + +- **Седмица 4 (09.11.2016)** +[List comprehension ](lectures/04-list-comprehension/lcomprehension.md) +Задачи от часа: [listcomp.md](exercises/list-comp/listcomp.md) ([list-comp](exercises/list-comp)) +Домашно: [Пермутации](exercises/permutations/perm.md) ([permutations](exercises/permutations)) --- -# fp-haskell +**Допълнителни материали** +[Литература, среда и др.](lectures/00-setup/extra.md) + diff --git a/exercises/colorize/Colorize.md b/exercises/colorize/Colorize.md index 26bad02..a0ea3c7 100644 --- a/exercises/colorize/Colorize.md +++ b/exercises/colorize/Colorize.md @@ -6,6 +6,9 @@ import Colorize hiding (mkStyle, mkTextStyle) ``` --> +Colorize +==== + Хаки МакХакер, син на най-уважаваните програмисти в Ламбда Ленд, тамън започва да се учи да програмира. Амбициозните му родители са му дали за задача да принтира цветен текст по терминала на Линукската му машина. Хаки, незнаейки как да се справи, е решил да потърси решение в интернет форумите. След любезно запитаване в БезкрайнаРекурсия, Ти си видял въпроса му. Вече преминал обичайните чудения дали да го downvote-неш, че пита нещо очевидно, или че е поредният ученик търсещ бързо решение на домашното си, виждаш че той е положил усиля, като е прочел в WikiLambdia и се е опитал да достигне до решение, но без успех. От прочита на WikiLambdia, Хаки е дефинирал няколко цветови константи и е написал заготовки ([stubs](https://en.wikipedia.org/wiki/Stub)) на функциите `colorize` и `bleach`. diff --git a/exercises/list-comp/listcomp.hs b/exercises/list-comp/listcomp.hs new file mode 100644 index 0000000..2c2bc23 --- /dev/null +++ b/exercises/list-comp/listcomp.hs @@ -0,0 +1,31 @@ +{-# OPTIONS_GHC -Wall #-} +module ListComp where + +myLength :: [Int] -> Int +myLength list = sum [ 1 | _ <- list] + +myElem :: Int -> [Int] -> Bool +myElem e list = not (null [x | x <- list, x == e]) + +myElem':: Int -> [Int] -> Bool +myElem' e l = and [True | x <- l, x == e] + +myElem'':: Int -> [Int] -> Bool +myElem'' e l = or [ x == e | x <- l] + +count :: Int -> [Int] -> Int +count e l = myLength [x | x <- l, x == e] + + +arithmeticSeries :: Int -> Int -> Int -> [Int] +arithmeticSeries a incrementator n = [a + x*incrementator | x <- [0..n-1]] + +arithmeticSum :: Int -> Int -> Int -> Int +arithmeticSum a incrementator n = sum (arithmeticSeries a incrementator n) + +geometricSeries :: Double -> Double -> Int -> [Double] +geometricSeries a q n = [a*q^x | x <- [0..n-1]] + +geometricSum :: Double -> Double -> Int -> Double +geometricSum a q n = sum (geometricSeries a q n) + diff --git a/exercises/list-comp/listcomp.md b/exercises/list-comp/listcomp.md new file mode 100644 index 0000000..699874b --- /dev/null +++ b/exercises/list-comp/listcomp.md @@ -0,0 +1,28 @@ +# List comprehensions + +- *Трансформацията с функция* на списък рекурсивно: + ```hs + f :: [Int] -> [Int] + f [] = [] + f (x:xs) = (някаквa-функция x) : f xs + ``` + e равносилна на: + ```hs + [някаква функция x | x <- входния-списък] + ``` +
+- Филтрацията на списък рекурсивно: + ```hs + g :: [Int] -> [Int] + g [] = [] + g (x:xs) + | някакво услове за x = g xs + | otherwise = x : g xs + ``` + е равносилна на: + ```hs + [ x | x<- входен списък, някакво услове за х] + ``` + + +### **[Кодът](listcomp.hs)**, който писахме в клас. diff --git a/exercises/lists/Lists.md b/exercises/lists/Lists.md index 6ee3de5..28d381d 100644 --- a/exercises/lists/Lists.md +++ b/exercises/lists/Lists.md @@ -11,19 +11,6 @@ import Prelude hiding ( ``` --> -Домашно №2 -===== - -Имплементирайте следните функции: - - [elem](#elem) - - [sum](#sum) - - [replicate](#replicate) - - [interleave](#interleave) - -Бонус: всички останли. Започнте с тези за множества - [Списъци като множества](#Списъци-като-множества) - ---- - Работа със списъци ====== diff --git a/exercises/lists/ListsHW.md b/exercises/lists/ListsHW.md new file mode 100644 index 0000000..9a8cf80 --- /dev/null +++ b/exercises/lists/ListsHW.md @@ -0,0 +1,10 @@ +Домашно Lists +===== + +Имплементирайте следните функции: + - [elem](Lists.md#elem) + - [sum](Lists.md#sum) + - [replicate](Lists.md#replicate) + - [interleave](Lists.md#interleave) + +Бонус: всички останли. Започнте с тези за множества - [Списъци като множества](Lists.md#Списъци-като-множества) diff --git a/exercises/permutations/perm.hs b/exercises/permutations/perm.hs new file mode 100644 index 0000000..12547ba --- /dev/null +++ b/exercises/permutations/perm.hs @@ -0,0 +1,7 @@ +module Permutations where + +import Data.List hiding (permutations) + +permutations :: [Int] -> [[Int]] +permutations = undefined + diff --git a/exercises/permutations/perm.md b/exercises/permutations/perm.md new file mode 100644 index 0000000..02e8529 --- /dev/null +++ b/exercises/permutations/perm.md @@ -0,0 +1,21 @@ + +Пермутации +==== + +## Описание + +Имплементерайте функцията `permutations:: [Int] -> [[Int]]`, която приема списък от числа и връща всички възможни [пермутации](https://www.mathsisfun.com/definitions/permutation.html). + + +## Примерен вход и изход + +```hs +>permutations [1,2,3] + +[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] +``` +## Бонус +Напишете функцията, като използвате най-много 200 символа (и без да сменяте името)! + +### Насока +Броят на всички възможни пермутации на лист с `n` елемента е `n!`. Знаем, че `0! = 1`, какво трябва да връщаме при `permutations []`? diff --git a/exercises/secret-lang/Secret-lang.md b/exercises/secret-lang/Secret-lang.md index 21289eb..eeaf73c 100644 --- a/exercises/secret-lang/Secret-lang.md +++ b/exercises/secret-lang/Secret-lang.md @@ -1,4 +1,7 @@ -# Описание +Езика на разбойниците +==== + +## Описание Много малки деца си измислят и използват *супер тайни езици*, за да крият информация и объркват родителите си. По всяка вероятност всеки може да се сети за поне няколко такива (например *пилешки говор* на български); явлението е толкова разпространено, че Wikipedia дори има [списък на най-известните такива езици](https://en.wikipedia.org/wiki/Language_game#List_of_common_language_games).

@@ -9,19 +12,19 @@ Напишете програма, коята кодира низ нормален текст на тайния Rövarspråket. -# Примерен вход и изход +## Примерен вход и изход Вход: `I'm speaking Robber's language!` Изход: `I'mom sospopeakokinongog Rorobobboberor'sos lolanongoguagoge!` -# Бонус #1 +## Бонус #1 Уверете се, че програмата ви работи правилно с главни букви. Така например `Hello` трябва да се преведе до `Hohelollolo`, а не `HoHelollolо`. Вижте функцията `toLower` в модула `Data.Char` и как може да я импортирате. -# Бонус #2** +## Бонус #2** Напишете функция, която декодира низ обратно към нормален език *(допуснете, че даденият текст е във валиден Rövarspråket)*. Замислете се как бихте имплементирали и използвали функция `dropN`, която пропуска първите *n* символа от низ. -# Бележки +## Бележки След като сте разкрили една шведска тайна, е време да преминете към следващата - [Surströmming](https://www.youtube.com/watch?v=wapOib5u8a8) (чудя се това дали изобщо да го има). diff --git a/lectures/Readme.md b/lectures/00-setup/extra.md similarity index 100% rename from lectures/Readme.md rename to lectures/00-setup/extra.md diff --git a/lectures/00-setup/setup.md b/lectures/00-setup/setup.md index d12490c..ae1ba4f 100644 --- a/lectures/00-setup/setup.md +++ b/lectures/00-setup/setup.md @@ -3,8 +3,8 @@ *page_number:false --> -Функционално Програмиране с Haskell -== +Относно курса +==== Георги Наков, [nakov.gl at gmail com](mailto:nakov.gl+tues@gmail.com) Марин Маринов, [marinov.ms+ tues at gmail com](mailto:marinov.ms+tues@gmail.com) @@ -39,4 +39,4 @@ extra-include-dirs: C:\Program Files\Haskell Platform\7.10.3\mingw\include ``` - *(не препоръчваме да използвате Windows)* \ No newline at end of file + *(не препоръчваме да използвате Windows)* diff --git a/lectures/01-intro/intro.md b/lectures/01-intro/intro.md index d3e3365..416eb80 100644 --- a/lectures/01-intro/intro.md +++ b/lectures/01-intro/intro.md @@ -3,10 +3,8 @@ *page_number:false --> -Въведение във -Функционалното Програмиране. -История на Haskell -== +Що е то функционално програмиране?
История на Haskell +====

@@ -82,11 +80,11 @@ - резултатите от функции **не** се изчисляват преди да се необходими - практически неприложимо при функции със странични ефекти ```hs -f x y z = - if x>0 then x+y else x+z +f x y z = if x>0 then x+y else x+z -f (5*6) (10-7) (5/0) +> f (5*6) (10-7) (5/0) -- не се хвърля грешка +33 ``` --- ## Мързеливо оценяване diff --git a/lectures/02-syntax-and-types/syntax-and-types.md b/lectures/02-syntax-and-types/syntax-and-types.md new file mode 100755 index 0000000..c457f58 --- /dev/null +++ b/lectures/02-syntax-and-types/syntax-and-types.md @@ -0,0 +1,365 @@ + + +Въведение в Haskell.
Основени типове и синтаксис. +==== + +
+
+
+ +Георги Наков, [nakov.gl at gmail com](mailto:nakov.gl+tues@gmail.com) +Марин Маринов, [marinov.ms+tues at gmail com](mailto:marinov.ms+tues@gmail.com) + +Технологично училище "Електронни Системи" +19 Октомври 2016г. + +--- + +## Какво е Haskell + + - стриктно типуван + - (lazy) pure functional language + - с кратък, странен, но елегантен и удобен синтаксис + +--- + +## Деклариране на променливи + +```hs +i :: Int +i = 3 + +c :: Char +c = 'c' + +d :: Double +d = 3.0 +``` + +--- + +## Анатомия на дефинициите - сигнатурата + + +```hs +i :: Int +``` + + - деклариране на променлива `i` + - `::` оператор, който означава _има тип_ + - самият тип - Int + +--- + +## Анатомия на дефинициите - променливата + + +```hs +i = 3 +i = 4 -- compile-time error +``` + + - в Haskell променливите не са "променливи", а дефиниция или наименование на стойност - един път зададена такава, тя не може да бъде мутирана или повторно задавана + - операторът за присвояване е `=` + +--- + +## Type Inference + +Haskell сам може да открие типовете, без да му бъдат подадени. Програмата винаги е добре типувана (дори при изпуснати сигнатури) и ако има грешки или двусмислие ще бъдат хванати при компилация. +
+ +```hs +c' = 'e' -- inferred as Char +``` + +
**Добра практика**: винаги пишете сигнатурите на всички не-вгнездени дефиниции + +--- + +## Основни типове + +| Тип | Стойности | +|----------------------------|-------------------------| +| Bool | `True`, `False` | +| Int (32/64 bit) | `0`, `1`, `2`, `3`, .. | +| Double | `0.0`, `0.5`, `1.33` | +| Char | `'a'`, `'b'`, `'c'` | +| Integer - произволно голям | `1234567890123456789..` | + +
**Забележка:** Синтаксисът на езика изисква типовете винаги да започват с главна буква. Променливите (било то константи или имена на функции), задължително започват с малка. + +--- + +## Именоване на променливи + + - винаги започват с малка буква + - състоят се от unicode букви, цифри и символът `'` + - символът `'` (секонд) се използва са повторна/спомагателна дефиниция + - по конвенция се ползва camelCase пред snake_case +
+ +```hs +fairRandom = 4 + +diceRoll = 6 +diceRoll' = 3 + +theZCharacter = 'z' +``` + +--- + +## Булеви алгебра + +Haskell използва познатите оператори за логическите операции. + +`&&` - логическо и +`||` - логическо или +`not` - логическо отрицание, не е оператор, а функция + +
+ +```hs +> True && False +False + +> True || False +True + +> not True +False +``` + +--- + +## Оператори за сравнение + + +| Оператор | Значение | +|----------|---------------------| +| `==` | равно / еднакво | +| `/=` | неравно / различно | +| `<` | по-малко | +| `>` | по-голямо | +|`<=` | по-малко или равно | +|`>=` | по-голямо или равно | + + +
**Забележка:** Сравнителните оператори в Haskell са същите като в повечето други езици, с изключение на различно - `/=`. + +--- + +## Операции върху числа + +Аритметичните операции са в голямата си част както в другите езици и притежават обичайните свойства - `+`, `-`, `*` + +```hs +> 3 + 4 * 5 +-- 3 + (4 * 5) +23 + +> 1 + (-2) - 3 +-4 +``` + +
**Hint:** Обграждайте отрицателните числа в скоби (пр. `(-2)`). В противен случай на много места компилаторът ще се оплаква със странни грешки. + +--- + +## Целочислено деление + +Делението на цели числа става посредством функциите `div` и `quot`: + +```hs +> quot 10 5 +2 + +> quot (-4) 3 +-1 + +> div (-4) 3 +-2 +``` + +
**Hint:** използвайте `quot` за (интуитивно) поведение като в C. Разликата между двата операторa е само при деление на числа с различни знаци. + +--- + +## Нецелочислено деление + +Операторът за нецелочислено деление е познатият `/` +```hs +> 3 / 4 +0.75 + +> (-5) / 2 +-2.5 + +> 10 / 2.5 +4.0 +``` + +--- + +## Работа с функции - извикване + + - извикването на функция става без скоби + - параметрите се подават в реда, в който функцията ги очаква, разделени с празно (whitespace) + - извикването на функция е операцията с най-висок приоритет + - ако е нужна промяна на приоритета се използват скоби + +```hs +> quot 4 2 +2 + +> quot 20 2 * 5 + -- (quot 20 2) * 5 +50 + +> quot 20 (2 * 5) + -- quot 20 10 +2 +``` + +--- + +## Сигнатура на функция + +```hs +quot :: Int -> Int -> Int + | | | | + name arg1 arg2 result +``` + +Сигнатурата на функция представлява изброени аргументите, които тя приема, последвани от резултатния тип, разделени със знака `->` помежду им. + +**Как се чете:** `quot` е функция която приема два аргумента от тип `Int` и връща като резултат `Int`. + +--- +## Сигнатура на функция +
+ +```hs +parseNumber :: String -> Int +``` + +Е функция която приема `String` и връща `Int`. +
+ +```hs +mishmash :: Int -> Bool -> String -> CustomType + +> mishmash 10 False "string" +-- some value of type CustomType +``` + +--- + +## Дефиниране на функция +
+ +Синтаксис: +```hs +funtionName arg1 arg2 argN = definition +``` + +
Пример: +```hs +add3 :: Int -> Int -> Int -> Int +add3 x y z = x + y + z + +> add3 100 1000 (-1) +1099 +``` + +--- + +## GHCi + +Това е интерактивен Haskell REPL. Повечето програми, които ще пишем, няма да компилираме до executables, а ще ги използваме през GHCi с цел по-лесна, интерактивна и бърза работа. Haskell е известен с относително сложния си модел на IO. Нека това не ви безпокои, нито отказва. Ще стигнем до там, но преди това трябва да се заредим с по-базовите средства и концепции :) + +--- + +## GHCi - команди + +`:l ` - служи за зареждане на сорс файла достъпен на съответния път + +```text +:l Demo.hs +[1 of 1] Compiling Demo ( Demo.hs, interpreted ) +Ok, modules loaded: Demo. +``` + +
`:r` - презареждане на вече заредени сорсове +```text +:r +[1 of 1] Compiling Demo ( Demo.hs, interpreted ) +Ok, modules loaded: Demo. +``` + +--- + +## GHCi - команди + +`:t ` - показва типа на съответния _expression_ + +```text +> :t True +True :: Bool + +> :t 10 +10 :: Num a => a + +> :t (2 + 2) +(2 + 2) :: Num a => a + +> :t words +words :: String -> [String] +``` + +--- + +**Важно:** не се притеснявайте, че типът на числата не е `Int`, а `Num a => a`. Това е генерализиран тип за число. Не се плашете и от малките букви! В следващите няколко урока ще стигнем до тях - с времето и вие ще станете тъмни магьосници, но първо трябва да минем базовите неща! + +--- + +## GHCi - команди + +`:i ` - показа информация за дадената променлива с име _identifier_, какъв й е типът и къде е дефинирана + +
+ +```text +> :i words + +words :: String -> [String] + -- Defined in ‘base-4.8.2.0:Data.OldList’ +``` + +--- + +## GHCi - други полезни команди + +Тези команди са общовалидни за терминала и са част от така нареченият emacs mode. Повечето приложения, които има някаква форма на интеракция, използват именно тези shortcuts. + +--- + +| Команда | Използване | +|----------|---------------------------------------------| +| tab | допълване / completion | +| Ctrl + r | reverse search - търси в историята на вече въвежданите команди | +| Ctrl + a | изместване на курсора в началото на реда | +| Ctrl + e | изместване на курсора в края на реда | +| Ctrl + w | изтриване на думата, при/преди курсора | +| Ctrl + d | спира текущия shell / command line програма | +| Ctrl + l | почиства екрана | + +--- + +## GHCi - последни думи + +Не използвайте GHCi за големи дефиниции (примерно на функции). GHCi не работи добре за въвеждане на многоредов код, затова е препоръчително кодът да е във файл, а в GHCi само да бъде презареждан и отделните функции тествани. Разглеждане на типове, малки експерименти и тестове са силните страни на всеки REPL. diff --git a/lectures/02-basics/linked-list.png b/lectures/03-lists-guards-patterns/linked-list.png similarity index 100% rename from lectures/02-basics/linked-list.png rename to lectures/03-lists-guards-patterns/linked-list.png diff --git a/lectures/02-basics/basics.md b/lectures/03-lists-guards-patterns/lists-guards-patterns.md old mode 100755 new mode 100644 similarity index 54% rename from lectures/02-basics/basics.md rename to lectures/03-lists-guards-patterns/lists-guards-patterns.md index b537825..51d663e --- a/lectures/02-basics/basics.md +++ b/lectures/03-lists-guards-patterns/lists-guards-patterns.md @@ -3,8 +3,8 @@ *page_number:false --> -Въведение в Haskell
Основен синтаксис и типове -== +Въведение част 2
Lists, Guards and Pattern matching +====

@@ -14,269 +14,10 @@ Марин Маринов, [marinov.ms+tues at gmail com](mailto:marinov.ms+tues@gmail.com) Технологично училище "Електронни Системи" -19 Октомври 2016г. +26 Октомври 2016г. --- -## Какво е Haskell - - - стриктно типуван - - (lazy) pure functional language - - с кратък, странен, но елегантен и удобен синтаксис - ---- - -## Деклариране на променливи - -```hs -i :: Int -i = 3 - -c :: Char -c = 'c' - -d :: Double -d = 3.0 -``` - ---- - -## Анатомия на дефинициите - сигнатурата - - -```hs -i :: Int -``` - - - деклариране на променлива `i` - - `::` оператор, който означава _има тип_ - - самият тип - Int - ---- - -## Анатомия на дефинициите - променливата - - -```hs -i = 3 -i = 4 -- compile-time error -``` - - - в Haskell променливите не са "променливи", а дефиниция или наименование на стойност - един път зададена такава, тя не може да бъде мутирана или повторно задавана - - операторът за присвояване е `=` - ---- - -## Type Inference - -Haskell сам може да открие типовете, без да му бъдат подадени. Програмата винаги е добре типувана (дори при изпуснати сигнатури) и ако има грешки или двусмислие ще бъдат хванати при компилация. -
- -```hs -c' = 'e' -- inferred as Char -``` - -
**Добра практика**: винаги пишете сигнатурите на всички не-вгнездени дефиниции - ---- - -## Основни типове - -| Тип | Стойности | -|----------------------------|-------------------------| -| Bool | `True`, `False` | -| Int (32/64 bit) | `0`, `1`, `2`, `3`, .. | -| Double | `0.0`, `0.5`, `1.33` | -| Char | `'a'`, `'b'`, `'c'` | -| Integer - произволно голям | `1234567890123456789..` | - -
**Забележка:** Синтаксисът на езика изисква типовете винаги да започват с главна буква. Променливите (било то константи или имена на функции), задължително започват с малка. - ---- - -## Именоване на променливи - - - винаги започват с малка буква - - състоят се от unicode букви, цифри и символът `'` - - символът `'` (секонд) се използва са повторна/спомагателна дефиниция - - по конвенция се ползва camelCase пред snake_case -
- -```hs -fairRandom = 4 - -diceRoll = 6 -diceRoll' = 3 - -theZCharacter = 'z' -``` - ---- - -## Булеви алгебра - -Haskell използва познатите оператори за логическите операции. - -`&&` - логическо и -`||` - логическо или -`not` - логическо отрицание, не е оператор, а функция - -
- -```hs -> True && False -False - -> True || False -True - -> not True -False -``` - ---- - -## Оператори за сравнение - - -| Оператор | Значение | -|----------|---------------------| -| `==` | равно / еднакво | -| `/=` | неравно / различно | -| `<` | по-малко | -| `>` | по-голямо | -|`<=` | по-малко или равно | -|`>=` | по-голямо или равно | - - -
**Забележка:** Сравнителните оператори в Haskell са същите като в повечето други езици, с изключение на различно - `/=`. - ---- - -## Операции върху числа - -Аритметичните операции са в голямата си част както в другите езици и притежават обичайните свойства - `+`, `-`, `*` - -```hs -> 3 + 4 * 5 --- 3 + (4 * 5) -23 - -> 1 + (-2) - 3 -0 -``` - -
**Hint:** Обграждайте отрицателните числа в скоби (пр. `(-2)`). В противен случай на много места компилаторът ще се оплаква със странни грешки. - ---- - -## Целочислено деление - -Делението на цели числа става посредством функциите `div` и `quot`: - -```hs -> quot 10 5 -2 - -> quot (-4) 3 --1 - -> div (-4) 3 --2 -``` - -
**Hint:** използвайте `quot` за (интуитивно) поведение като в C. Разликата между двата операторa е само при деление на числа с различни знаци. - ---- - -## Нецелочислено деление - -Операторът за нецелочислено деление е познатият `/` -```hs -> 3 / 4 -0.75 - -> (-5) / 2 --2.5 - -> 10 / 2.5 -4.0 -``` - ---- - -## Работа с функции - извикване - - - извикването на функция става без скоби - - параметрите се подават в реда, в който функцията ги очаква, разделени с празно (whitespace) - - извикването на функция е операцията с най-висок приоритет - - ако е нужна промяна на приоритета се използват скоби - -```hs -> quot 4 2 -2 - -> quot 20 2 * 5 - -- (quot 20 2) * 5 -50 - -> quot 20 (2 * 5) - -- quot 20 10 -2 -``` - ---- - -## Сигнатура на функция - -```hs -quot :: Int -> Int -> Int - | | | | - name arg1 arg2 result -``` - -Сигнатурата на функция представлява изброени аргументите, които тя приема, последвани от резултатния тип, разделени със знака `->` помежду им. - -**Как се чете:** `quot` е функция която приема два аргумента от тип `Int` и връща като резултат `Int`. - ---- -## Сигнатура на функция -
- -```hs -parseNumber :: String -> Int -``` - -Е функция която приема `String` и връща `Int`. -
- -```hs -mishmash :: Int -> Bool -> String -> CustomType - -> mishmash 10 False "string" --- some value of type CustomType -``` - ---- - -## Дефиниране на функция -
- -Синтаксис: -```hs -funtionName arg1 arg2 argN = definition -``` - -
Пример: -```hs -add3 :: Int -> Int -> Int -> Int -add3 x y z = x + y + z - -> add3 100 1000 (-1) -1099 -``` - ---- ## Дефиниране на частни случаи Може да имаме отделни случаи (с различно тяло) за конкретни стойности на аргументите на функция. @@ -674,91 +415,3 @@ reverseKeys [] = [] > reverseKeys "This is a Killer key" "This is a liKler yek" ``` - ---- - -## GHCi - -Това е интерактивен Haskell REPL. Повечето програми, които ще пишем, няма да компилираме до executables, а ще ги използваме през GHCi с цел по-лесна, интерактивна и бърза работа. Haskell е известен с относително сложния си модел на IO. Нека това не ви безпокои, нито отказва. Ще стигнем до там, но преди това трябва да се заредим с по-базовите средства и концепции :) - ---- - -## GHCi - команди - -`:l ` - служи за зареждане на сорс файла достъпен на съответния път - -```text -:l Demo.hs -[1 of 1] Compiling Demo ( Demo.hs, interpreted ) -Ok, modules loaded: Demo. -``` - -
`:r` - презареждане на вече заредени сорсове -```text -:r -[1 of 1] Compiling Demo ( Demo.hs, interpreted ) -Ok, modules loaded: Demo. -``` - ---- - -## GHCi - команди - -`:t ` - показва типа на съответния _expression_ - -```text -> :t True -True :: Bool - -> :t 10 -10 :: Num a => a - -> :t (2 + 2) -(2 + 2) :: Num a => a - -> :t words -words :: String -> [String] -``` - ---- - -**Важно:** не се притеснявайте, че типът на числата не е `Int`, а `Num a => a`. Това е генерализиран тип за число. Не се плашете и от малките букви! В следващите няколко урока ще стигнем до тях - с времето и вие ще станете тъмни магьосници, но първо трябва да минем базовите неща! - ---- - -## GHCi - команди - -`:i ` - показа информация за дадената променлива с име _identifier_, какъв й е типът и къде е дефинирана - -
- -```text -> :i words - -words :: String -> [String] - -- Defined in ‘base-4.8.2.0:Data.OldList’ -``` - ---- - -## GHCi - други полезни команди - -Тези команди са общовалидни за терминала и са част от така нареченият emacs mode. Повечето приложения, които има някаква форма на интеракция, използват именно тези shortcuts. - ---- - -| Команда | Използване | -|----------|---------------------------------------------| -| tab | допълване / completion | -| Ctrl + r | reverse search - търси в историята на вече въвежданите команди | -| Ctrl + a | изместване на курсора в началото на реда | -| Ctrl + e | изместване на курсора в края на реда | -| Ctrl + w | изтриване на думата, при/преди курсора | -| Ctrl + d | спира текущия shell / command line програма | -| Ctrl + l | почиства екрана | - ---- - -## GHCi - последни думи - -Не използвайте GHCi за големи дефиниции (примерно на функции). GHCi не работи добре за въвеждане на многоредов код, затова е препоръчително кодът да е във файл, а в GHCi само да бъде презареждан и отделните функции тествани. Разглеждане на типове, малки експерименти и тестове са силните страни на всеки REPL. diff --git a/lectures/03-polymorphism/lcomprehension.md b/lectures/04-list-comprehension/lcomprehension.md similarity index 88% rename from lectures/03-polymorphism/lcomprehension.md rename to lectures/04-list-comprehension/lcomprehension.md index 6302abf..4a7468e 100644 --- a/lectures/03-polymorphism/lcomprehension.md +++ b/lectures/04-list-comprehension/lcomprehension.md @@ -2,9 +2,15 @@ page_number:true *page_number:false --> + List comprehension
-== +====

@@ -42,9 +48,8 @@ List comprehension

```hs > [ x*2 | x <- [1..4]] - [2, 4, 6, 8] - ``` +``` --- @@ -68,7 +73,6 @@ List comprehension
- Може да взимаме няколко променливи, всяка взета от различен списък ```hs > [[x, y, z] | x <- [1..3], y <- [10,11], z <- [20,21]] - [[1, 10, 20], [1, 10, 21], [1, 11, 20], [1, 11, 21], [2, 10, 20], [2, 10, 21], [2, 11, 20], [2, 11, 21], [3, 10, 20], [3, 10, 21], [3, 11, 20], [3, 11, 21]] @@ -87,24 +91,22 @@ List comprehension
## List comprehension - Когато задаваме повече от един списък, може да използваме всички предишни променливи при дефиницията на списъка ```hs - > [ [x, y] | x <- [1..4], y <-[1..x]] - - [ [1, 1], - [2, 1], [2, 2], - [3, 1], [3, 2], [3, 3] - [4, 1], [4, 2], [4, 3], [4, 4] ] +> [ [x, y] | x <- [1..4], y <-[1..x]] + [ [1, 1], + [2, 1], [2, 2], + [3, 1], [3, 2], [3, 3], + [4, 1], [4, 2], [4, 3], [4, 4] ] ``` --- ## List comprehension - Може да вгнездваме list comprehension-и ```hs -removeEs :: [String]->[String] +removeEs :: [String] -> [String] removeEs someWords = - [ [c | c <- word, c /= 'е', c /= 'E'] - | word <- someWords]] + [ [c | c <- word, c /= 'e', c /= 'E'] + | word <- someWords] -> removeЕs ["These", "are", "some", "good", "words"] - - ["Ths", "r", "som", "good", "words"] +> removeEs ["These", "are", "some", "good", "words"] + ["Ths", "ar", "som", "good", "words"] ``` diff --git a/lectures/04-let-where/let-where.md b/lectures/05-polymorphism-let-where/let-where.md similarity index 100% rename from lectures/04-let-where/let-where.md rename to lectures/05-polymorphism-let-where/let-where.md diff --git a/lectures/03-polymorphism/poly.md b/lectures/05-polymorphism-let-where/poly.md similarity index 94% rename from lectures/03-polymorphism/poly.md rename to lectures/05-polymorphism-let-where/poly.md index 6b772e4..22245d7 100644 --- a/lectures/03-polymorphism/poly.md +++ b/lectures/05-polymorphism-let-where/poly.md @@ -2,7 +2,12 @@ page_number:true *page_number:false --> + Полиморфични функции
== @@ -26,13 +31,13 @@ Досега видяхме, че ако ни се налага да работим с различни видове списъци, трябва да пишем функциите по няколко пъти с различни сигнатури, но еднакви дефиниции.
```hs -lenght :: [Int] -> Int -length [] = 0 -length (_:xs) = 1 + length xs +lengthInt :: [Int] -> Int +lengthInt [] = 0 +lengthInt (_:xs) = 1 + lengthInt xs lengthString :: String -> Int lengthString [] = 0 -lengthString (_:xs) 1 + lengthString xs +lengthString (_:xs) = 1 + lengthString xs ``` Това е ужасно! @@ -60,17 +65,20 @@ length (_:xs) = 1 + length xs Вградените функции за манипулация на списъци в Haskell работят с списъци от какъвто и да е тип! Да проверим сигнатурите: ```hs > head [1, 2, 3] -1 +1 + > head "Hi" 'H' +``` -ghci>:t head +```text +ghci> :t head head :: [a] -> a -ghci>:t reverse +ghci> :t reverse reverse :: [a] -> [a] -ghci>:t (++) +ghci> :t (++) (++) :: [a] -> [a] -> [a] ``` --- @@ -78,7 +86,7 @@ ghci>:t (++) ## Полиморфични функции - начин на работа Не може да предполагаме нищо за аргументите или променливите, които са от тип `a`. Не може да извършваме операции с тях. -```hs +```hs bad :: a -> Int bad x = x + 1 -- грешка @@ -91,7 +99,7 @@ bad x = x + 1 В рамките на едно извикване на полиморфичните функции, `a` заема конкретен тип, който не се сменя по време на изпълнението на функцията. `a` има само един конкретен тип в рамките на извикването *(тоест не може при първия аргумент да е `Char`, вторият - `Int` и тн)*. -```hs +```text ghci> :t (++) (++) :: [a] -> [a] -> [a] @@ -120,7 +128,7 @@ ghci> :t ("Hi" ++ " all") ## Ограничения В някои случаи искаме да използваме полиморфична функция, но и някакво свойство на `a`. -```hs +```hs elem :: a -> [a] -> Bool elem _ [] = False elem e (x:xs) @@ -135,7 +143,7 @@ elem e (x:xs) ## Oграничения Решение: Може да кажем, че `a` трябва да поддържа сравнение за равенство с `(Eq a) =>` пред сигнатурата. -```hs +```hs elem :: (Eq a) => a -> [a] -> Bool ``` `(Eq a) =>` наричаме класови ограничение *(class constraint)*. @@ -152,6 +160,7 @@ equals x y = x == y > equals 3 3 True + > equals "Hi" "hi" False ``` @@ -163,9 +172,10 @@ False toString :: (Show a) => a -> String toString x = show x ->toString 4 +> toString 4 "4" ->toString [42,0] -"[42, 0]" + +> toString [42,0] +"[42,0]" ``` -Вградените стандартни типове (числа, низ, симвoли) поддържат и `Eq a` и `Show a`. \ No newline at end of file +Вградените стандартни типове (числа, низ, симвoли) поддържат и `Eq a` и `Show a`.