Haskell
Haskell — це чиста функціональна мова програмування зі статичною типізацією, lazy evaluation, immutable data, algebraic data types, pattern matching, type classes і сильним акцентом на математичну коректність програм.
Haskell часто використовують для навчання функціональному мисленню, компіляторів, формальних моделей, financial systems, backend-сервісів, DSL, research, high-assurance code, parserів, складної бізнес-логіки й задач, де типи можуть запобігти великій кількості помилок.
Коротко: Haskell — це мова, де функції чисті, дані immutable, типи дуже сильні, а side effects явно контролюються. Вона вимагає іншого мислення, але допомагає писати дуже передбачуваний код.
Офіційна сторінка Haskell описує мову як purely functional programming language із referential transparency, immutability і lazy evaluation. [1]
Головна ідея
Головна ідея Haskell — будувати програми як композицію чистих функцій і точно описаних типів.
У звичайному імперативному стилі програма часто змінює стан:
- змінні перезаписуються;
- об’єкти мутують;
- функції можуть змінювати глобальні дані;
- side effects приховані;
- порядок виконання дуже важливий.
У Haskell підхід інший:
- значення immutable;
- функції не змінюють світ без явного типу;
- типи описують можливі стани;
- багато помилок ловить компілятор;
- програма будується через композицію функцій.
Проста аналогія: Haskell змушує спочатку чітко описати “які значення можливі”, а вже потім писати код. Це схоже на креслення перед будівництвом, а не ремонт під час руху.
Актуальний стан інструментів
Станом на травень 2026 року офіційна сторінка GHC показує серед останніх релізів GHC 9.12.4 від 27 березня 2026 року і GHC 9.14.1 від 19 грудня 2025 року. [2]
Офіційна сторінка Haskell Downloads рекомендує встановлювати Haskell через GHCup, який може встановити GHC, cabal-install, Stack і Haskell Language Server. [3]
GHC також запровадив LTS-підхід: Haskell.org повідомляв, що GHC починає підтримувати LTS release/branch із довшим періодом підтримки, орієнтовно від двох до трьох років. [4]
Для документації: у Haskell-проєктах важливо фіксувати версії GHC, Cabal/Stack і package set. Різні версії compiler і dependencies можуть суттєво впливати на build.
GHC
GHC або Glasgow Haskell Compiler — головний компілятор Haskell.
GHC включає:
- compiler;
- runtime system;
- GHCi;
- optimizer;
- extensions;
- profiling support;
- documentation;
- libraries;
- package support.
GHC є фактичним стандартом для сучасного Haskell.
Офіційна сторінка GHC описує його як state-of-the-art open source compiler and interactive environment for Haskell. [5]
GHCi
GHCi — інтерактивне середовище Haskell.
Приклад:
ghci Prelude> 2 + 3 5 Prelude> map (*2) [1,2,3] [2,4,6]
GHCi корисний для:
- навчання;
- швидкої перевірки functions;
- type exploration;
- debugging;
- prototyping;
- REPL workflow.
GHCup
GHCup — рекомендований installer і manager для Haskell toolchain.
Через GHCup можна встановлювати:
- GHC;
- cabal-install;
- Stack;
- Haskell Language Server.
Офіційна сторінка Haskell Downloads прямо рекомендує GHCup для Linux, macOS, FreeBSD, Windows або WSL2. [6]
Cabal
Cabal — build system і package description format для Haskell.
Cabal використовується для:
- опису packages;
- builds;
- dependencies;
- tests;
- benchmarks;
- library/executable targets;
- Hackage packages.
Типові команди:
cabal update cabal build cabal test cabal run
Haskell documentation page містить Cabal User Guide серед основних довідників Haskell tooling. [7]
Stack
Stack — альтернативний build tool для Haskell.
Stack фокусується на reproducible builds і curated package sets через Stackage.
Документація Stack описує, що Stack керує GHC installations і автоматично вибирає потрібну версію GHC для проєкту. [8]
Типові команди:
stack new my-project stack build stack test stack run
Haskell Language Server
Haskell Language Server або HLS — language server для редакторів.
Він дає:
- автодоповнення;
- diagnostics;
- go to definition;
- hover info;
- code actions;
- formatting;
- type information;
- інтеграцію з VS Code, Vim, Emacs та іншими редакторами.
Haskell Language Server releases підтримують конкретні версії GHC, тому сумісність HLS і GHC потрібно перевіряти. [9]
Hackage
Hackage — центральний repository Haskell packages.
Там публікуються libraries і tools.
Hackage корисний для:
- пошуку libraries;
- перегляду package documentation;
- version history;
- dependencies;
- maintainers;
- source tarballs.
Перед використанням package варто перевіряти maintenance, compatibility, license і recent releases.
Stackage
Stackage — curated package set для Haskell.
Ідея Stackage — мати набір package versions, які разом проходять build.
Це допомагає зменшити dependency conflicts.
Stackage має:
- LTS snapshots;
- nightly snapshots;
- GHC version binding;
- curated ecosystem.
Наприклад, Stackage Nightly 2026-05-06 використовував GHC 9.12.4. [10]
Чиста функція
Чиста функція — функція, яка:
- для однакових inputs завжди повертає однаковий output;
- не змінює зовнішній стан;
- не має прихованих side effects.
Приклад:
add :: Int -> Int -> Int add a b = a + b
Ця функція чиста: вона лише обчислює суму.
Referential transparency
Referential transparency означає, що expression можна замінити його значенням без зміни поведінки програми.
Наприклад:
add 2 3
можна замінити на:
5
Це робить код передбачуванішим і полегшує reasoning.
Офіційна сторінка Haskell називає referential transparency однією з ключових властивостей мови. [11]
Immutability
У Haskell значення immutable за замовчуванням.
Приклад:
x = 10
Це не змінна у звичному імперативному сенсі. Це binding імені x до значення 10.
Immutability допомагає:
- уникати випадкової зміни стану;
- спрощувати reasoning;
- краще працювати з concurrency;
- зменшувати кількість bugs.
Lazy evaluation
Lazy evaluation означає, що вирази обчислюються не одразу, а коли результат справді потрібен.
Приклад:
take 5 [1..]
У Haskell це працює: нескінченний список [1..] не обчислюється повністю. Беруться лише перші 5 елементів.
Цікаво: lazy evaluation дозволяє працювати з потенційно нескінченними структурами. Але вона також може створювати performance surprises, якщо не розуміти, коли саме обчислюються значення.
Strictness
Strictness — протилежний підхід до lazy evaluation: значення обчислюється раніше.
У Haskell іноді потрібно явно керувати strictness, щоб уникнути:
- memory leaks;
- накопичення thunks;
- неочікуваного використання пам’яті;
- performance problems.
Для цього використовують:
- bang patterns;
- seq;
- strict data fields;
- strict libraries;
- profiling.
Thunk
Thunk — відкладене обчислення.
Через lazy evaluation Haskell може створювати thunks замість негайного обчислення значень.
Це корисно для laziness, але якщо thunks накопичуються, може зрости використання пам’яті.
Типи
Haskell має сильну статичну типізацію.
Приклад:
name :: String name = "Haskell" count :: Int count = 10
Типи допомагають:
- ловити помилки під час компіляції;
- документувати наміри;
- моделювати domain;
- забороняти неможливі стани;
- робити refactoring безпечнішим.
Type inference
Haskell має потужний type inference.
Можна написати:
double x = x * 2
GHC сам виведе тип.
Але в production-коді часто корисно писати type signatures:
double :: Num a => a -> a double x = x * 2
Type signatures документують код і допомагають ловити помилки раніше.
Algebraic Data Types
Algebraic Data Types або ADT — один із найсильніших інструментів Haskell.
Приклад:
data OrderStatus = Draft | Paid | Cancelled
Це означає: статус замовлення може бути тільки Draft, Paid або Cancelled.
ADT допомагають явно описувати domain states.
Product types і sum types
Product type містить кілька полів.
Приклад:
data Customer = Customer
{ customerId :: Int
, customerName :: String
}
Sum type описує вибір між варіантами.
Приклад:
data PaymentResult = PaymentOk | PaymentDeclined String | PaymentError String
Sum types дозволяють моделювати бізнес-логіку без неявних null або magic strings.
Pattern matching
Pattern matching — спосіб розібрати значення за формою.
Приклад:
statusText :: OrderStatus -> String statusText Draft = "Чернетка" statusText Paid = "Оплачено" statusText Cancelled = "Скасовано"
Pattern matching робить код дуже читабельним для обробки ADT.
Guards
Guards дозволяють писати умовну логіку.
Приклад:
discount :: Int -> Int discount amount | amount > 10000 = 20 | amount > 5000 = 10 | otherwise = 0
Guards часто роблять код чистішим, ніж nested if.
Maybe
Maybe — тип для значення, яке може бути відсутнім.
Приклад:
data Maybe a = Nothing | Just a
Практичне використання:
findCustomer :: Int -> Maybe Customer
Це означає: customer може бути знайдений або ні.
Практична користь: замість null Haskell використовує тип Maybe. Компілятор змушує вас обробити випадок, коли значення немає.
Either
Either часто використовується для результату з помилкою.
Приклад:
parseAmount :: String -> Either String Int
Це означає:
Right Int— успішний результат;Left String— помилка.
Either корисний для validation, parsing, API responses і business rules.
Type classes
Type class — механізм ad-hoc polymorphism.
Приклад:
class Printable a where printValue :: a -> String
Тип може мати instance:
instance Printable Customer where printValue customer = customerName customer
Type classes схожі на interfaces, але мають іншу семантику й велику роль у Haskell ecosystem.
Eq, Ord, Show, Read
Базові type classes:
Eq— порівняння на рівність;Ord— порядок;Show— перетворення в рядок;Read— читання з рядка.
Приклад:
data Status = Draft | Paid deriving (Eq, Show)
deriving автоматично створює instances.
Functor
Functor — type class для контейнерів або контекстів, над якими можна застосувати функцію.
Ключова функція:
fmap :: Functor f => (a -> b) -> f a -> f b
Приклад:
fmap (+1) (Just 10) -- Just 11
Functor дозволяє працювати з “значенням у контексті”, не витягуючи його вручну.
Applicative
Applicative — abstraction між Functor і Monad.
Вона дозволяє застосовувати function у контексті до value у контексті.
Приклад ідеї:
pure (+) <*> Just 2 <*> Just 3 -- Just 5
Applicative часто використовують у validation, parsing і configuration.
Monad
Monad — abstraction для послідовного поєднання обчислень у контексті.
Ключова ідея: результат одного кроку впливає на наступний крок.
Приклад із Maybe:
findCustomer customerId >>= findPrimaryEmail
Якщо customer не знайдено, наступний крок не виконується.
Без містики: монада — це не “магія”. Це спосіб акуратно з’єднувати обчислення, які мають контекст: Maybe, Either, IO, список, state, parser тощо.
IO Monad
IO — тип для операцій, які взаємодіють із зовнішнім світом.
Приклад:
main :: IO () main = putStrLn "Hello, Haskell"
IO потрібен для:
- читання файлів;
- запису файлів;
- network;
- database;
- console;
- random;
- time;
- взаємодії з OS.
Haskell не забороняє side effects. Він робить їх явними у типах.
do notation
do notation — синтаксис для послідовних monadic operations.
Приклад:
main :: IO ()
main = do
putStrLn "What is your name?"
name <- getLine
putStrLn ("Hello, " ++ name)
Це схоже на імперативний код, але типи все одно контролюють effects.
Higher-order functions
Haskell активно використовує functions як values.
Приклади:
map (*2) [1,2,3] filter even [1..10] foldr (+) 0 [1,2,3]
Higher-order functions дозволяють будувати дуже компактні transformations.
Function composition
Композиція функцій записується через ..
Приклад:
normalizeName :: String -> String normalizeName = trim . toLower
Це означає: спочатку toLower, потім trim.
Function composition — один із ключових стилів Haskell-коду.
Currying
У Haskell функції технічно приймають один аргумент і можуть повертати функцію.
Приклад:
add :: Int -> Int -> Int add a b = a + b
Це можна читати як:
Int -> (Int -> Int)
Тому можна частково застосовувати функції:
add10 = add 10 add10 5 -- 15
Recursion
У Haskell loops часто виражаються через recursion або higher-order functions.
Приклад:
sumList :: [Int] -> Int sumList [] = 0 sumList (x:xs) = x + sumList xs
У production-коді часто використовують готові functions на кшталт sum, map, fold.
Lists
List — базова структура даних.
Приклад:
numbers :: [Int] numbers = [1,2,3,4]
Операції:
head numbers tail numbers map (*2) numbers filter even numbers
- ↑ https://www.haskell.org/
- ↑ https://www.haskell.org/ghc/
- ↑ https://www.haskell.org/downloads/
- ↑ https://www.haskell.org/ghc/blog/20250702-ghc-release-schedules.html
- ↑ https://www.haskell.org/ghc/
- ↑ https://www.haskell.org/downloads/
- ↑ https://www.haskell.org/documentation/
- ↑ https://docs.haskellstack.org/en/stable/
- ↑ https://github.com/haskell/haskell-language-server/releases
- ↑ https://www.stackage.org/nightly-2026-05-06
- ↑ https://www.haskell.org/