Skip to content

Latest commit

 

History

History
executable file
·
365 lines (244 loc) · 10.9 KB

syntax-and-types.md

File metadata and controls

executable file
·
365 lines (244 loc) · 10.9 KB

Въведение в Haskell.
Основени типове и синтаксис.




Георги Наков, nakov.gl at gmail com
Марин Маринов, marinov.ms+tues at gmail com

Технологично училище "Електронни Системи"
19 Октомври 2016г.


Какво е Haskell

  • стриктно типуван
  • (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 променливите не са "променливи", а дефиниция или наименование на стойност - един път зададена такава, тя не може да бъде мутирана или повторно задавана
  • операторът за присвояване е =

Type Inference

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

GHCi

Това е интерактивен Haskell REPL. Повечето програми, които ще пишем, няма да компилираме до executables, а ще ги използваме през GHCi с цел по-лесна, интерактивна и бърза работа. Haskell е известен с относително сложния си модел на IO. Нека това не ви безпокои, нито отказва. Ще стигнем до там, но преди това трябва да се заредим с по-базовите средства и концепции :)


GHCi - команди

: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.

GHCi - команди

: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. Това е генерализиран тип за число. Не се плашете и от малките букви! В следващите няколко урока ще стигнем до тях - с времето и вие ще станете тъмни магьосници, но първо трябва да минем базовите неща!


GHCi - команди

:i <identifier> - показа информация за дадената променлива с име identifier, какъв й е типът и къде е дефинирана


> :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.