Георги Наков, nakov.gl at gmail com
Марин Маринов, marinov.ms+tues at gmail com
Технологично училище "Електронни Системи"
19 Октомври 2016г.
- стриктно типуван
- (lazy) pure functional language
- с кратък, странен, но елегантен и удобен синтаксис
i :: Int
i = 3
c :: Char
c = 'c'
d :: Double
d = 3.0
i :: Int
- деклариране на променлива
i
::
оператор, който означава има тип- самият тип - Int
i = 3
i = 4 -- compile-time error
- в Haskell променливите не са "променливи", а дефиниция или наименование на стойност - един път зададена такава, тя не може да бъде мутирана или повторно задавана
- операторът за присвояване е
=
Haskell сам може да открие типовете, без да му бъдат подадени. Програмата винаги е добре типувана (дори при изпуснати сигнатури) и ако има грешки или двусмислие ще бъдат хванати при компилация.
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
fairRandom = 4
diceRoll = 6
diceRoll' = 3
theZCharacter = 'z'
Haskell използва познатите оператори за логическите операции.
&&
- логическо и
||
- логическо или
not
- логическо отрицание, не е оператор, а функция
> True && False
False
> True || False
True
> not True
False
Оператор | Значение |
---|---|
== |
равно / еднакво |
/= |
неравно / различно |
< |
по-малко |
> |
по-голямо |
<= |
по-малко или равно |
>= |
по-голямо или равно |
Забележка: Сравнителните оператори в Haskell са същите като в повечето други езици, с изключение на различно - /=
.
Аритметичните операции са в голямата си част както в другите езици и притежават обичайните свойства - +
, -
, *
> 3 + 4 * 5
-- 3 + (4 * 5)
23
> 1 + (-2) - 3
-4
Hint: Обграждайте отрицателните числа в скоби (пр. (-2)
). В противен случай на много места компилаторът ще се оплаква със странни грешки.
Делението на цели числа става посредством функциите div
и quot
:
> quot 10 5
2
> quot (-4) 3
-1
> div (-4) 3
-2
Hint: използвайте quot
за (интуитивно) поведение като в C. Разликата между двата операторa е само при деление на числа с различни знаци.
Операторът за нецелочислено деление е познатият /
> 3 / 4
0.75
> (-5) / 2
-2.5
> 10 / 2.5
4.0
- извикването на функция става без скоби
- параметрите се подават в реда, в който функцията ги очаква, разделени с празно (whitespace)
- извикването на функция е операцията с най-висок приоритет
- ако е нужна промяна на приоритета се използват скоби
> quot 4 2
2
> quot 20 2 * 5
-- (quot 20 2) * 5
50
> quot 20 (2 * 5)
-- quot 20 10
2
quot :: Int -> Int -> Int
| | | |
name arg1 arg2 result
Сигнатурата на функция представлява изброени аргументите, които тя приема, последвани от резултатния тип, разделени със знака ->
помежду им.
Как се чете: quot
е функция която приема два аргумента от тип Int
и връща като резултат Int
.
parseNumber :: String -> Int
Е функция която приема String
и връща Int
.
mishmash :: Int -> Bool -> String -> CustomType
> mishmash 10 False "string"
-- some value of type CustomType
Синтаксис:
funtionName arg1 arg2 argN = definition
Пример:
add3 :: Int -> Int -> Int -> Int
add3 x y z = x + y + z
> add3 100 1000 (-1)
1099
Това е интерактивен Haskell REPL. Повечето програми, които ще пишем, няма да компилираме до executables, а ще ги използваме през GHCi с цел по-лесна, интерактивна и бърза работа. Haskell е известен с относително сложния си модел на IO. Нека това не ви безпокои, нито отказва. Ще стигнем до там, но преди това трябва да се заредим с по-базовите средства и концепции :)
:l <source_path>
- служи за зареждане на сорс файла достъпен на съответния път
:l Demo.hs
[1 of 1] Compiling Demo ( Demo.hs, interpreted )
Ok, modules loaded: Demo.
:r
- презареждане на вече заредени сорсове
:r
[1 of 1] Compiling Demo ( Demo.hs, interpreted )
Ok, modules loaded: Demo.
:t <expression>
- показва типа на съответния expression
> :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
. Това е генерализиран тип за число. Не се плашете и от малките букви! В следващите няколко урока ще стигнем до тях - с времето и вие ще станете тъмни магьосници, но първо трябва да минем базовите неща!
:i <identifier>
- показа информация за дадената променлива с име identifier, какъв й е типът и къде е дефинирана
> :i words
words :: String -> [String]
-- Defined in ‘base-4.8.2.0:Data.OldList’
Тези команди са общовалидни за терминала и са част от така нареченият 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 само да бъде презареждан и отделните функции тествани. Разглеждане на типове, малки експерименти и тестове са силните страни на всеки REPL.