Більшість задіяних у блокчейн-розробці мов програмування — об’єктно-орієнтовані мови, які входять до так званої імперативної парадигми: Solidity, Python, C++, Java. Але в міру розвитку блокчейн-індустрії дедалі більше інфраструктурних проектів звертаються до так званої декларативної парадигми, зокрема — до функціональних мов програмування. Серед таких проектів Ercoin, æternity, Arwave, Helium та інші.
У цьому спецпроєкті ми розповімо про функціональне програмування та його застосування в блокчейн-індустрії без єдиного рядка коду в тексті.
Для цього ми відповімо на запитання:
Спонсор спецпроєкту — æternity — блокчейн-платформа третього покоління для створення децентралізованих додатків і масштабованих смарт-контрактів. Блокчейн æternity написаний функціональною мовою програмування Erlang, а для розробки тьюринг-повних смарт-контрактів команда проєкту розробила власну функціональну мову Sophia. Щоб смарт-контракти в системі могли взаємодіяти із зовнішнім світом, у æternity реалізовано систему оракулів — спеціальних вузлів, що отримують і верифікують інформацію ззовні блокчейна. Масштабованість застосунків і смарт-контрактів у мережі досягається завдяки використанню p2p-каналів станів (state channels) — операція між сторонами обробляється в окремому каналі, а основний блокчейн працює як архів даних, до якого сторони звертаються в разі розбіжностей. Крім того, в æternity працює система ончейн-управління, побудована на принципах "рідкої демократії" (liquid democracy).
Приєднатися до російськомовної спільноти проєкту:
У співпраці з æternity ми готуємо ще кілька цікавих спецпроєктів.
Підписуйтесь на розсилку і не пропускайте нові спецпроєкти
Що таке функціональне програмування і як воно виникло?
Функціональне програмування (ФП) — декларативна парадигма програмування . Її зазвичай протиставляють більш відомій альтернативі — імперативній парадигмі програмування , зокрема — об’єктно-орієнтованому програмуванню (ООП). ФП — це підхід до розроблення комп’ютерних програм, у якому основний інструмент — математичні функції. Причому йдеться про чисті функції, чий результат залежить виключно від вхідних даних.
День народження людини — приклад чистої функції . Неважливо, в який момент ви запитаєте людину про день її народження, відповідь завжди буде одна й та сама.
З іншого боку, вік людини не буде чистою функцією. Час іде, а відповідь змінюватиметься залежно від того, коли ви запитаєте. Функція "вік" змінює значення через побічний ефект — перебіг часу.
Функціональне програмування побудоване на основі лямбда-обчислення — формальної системи, винайденої американським математиком Алонзо Черчем у 1930-х роках для дослідження проблем обчислюваності.
Алонзо Черч (1903‐1995)
Формальна система Черча ґрунтується на двох принципах:
1. Усі використовувані функції — чисті й видають один і той самий результат для тих самих ввідних даних. 2. Кожна функція інтерпретується як "чорний ящик". Ми не можемо знати, що відбувається всередині функції, і бачимо тільки вхідні дані та результат.
У лямбда-обчислюванні задіяні два основні типи сутностей:
1. Функції, які для простоти позначають грецькою буквою (звідси назва). Буква лямбда — просто спосіб сказати "функція" коротше. 2. Аргументи, до яких застосовуються функції. Аргумент може бути числом або навіть іншою функцією з власними аргументами.
Лямбда-обчислення залишалося набором теоретичних ідей і не було повністю застосовне до проблем і обмежень реального світу. Однак у 1958 інформатик з MIT Джон МакКарті представив мову List Processing , також відому як Lisp . Ця мова програмування походила з лямбда-числення і мала багато властивостей функціональних мов програмування. Тепер Lisp вважають прабатьком функціональних мов.
Алан Тьюринг (1912‐1954)
Цікавий факт: Черч працював над лямбда- численням у Прінстонському університеті та був науковим керівником батька інформатики Алана Тьюринга. Обидва цікавилися дослідженнями математичної логіки обчислень. Поки Алонзо Черч підходив до досліджень з боку чистих функцій, Тюрінг розробляв те, що ми тепер називаємо машиною Тюрінга — математичну модель обчислень, у якій уявна машина маніпулює символами на стрічці, згідно з набором правил.
Машина Тюрінга зчитує символ, звіряється з таблицею правил і виконує відповідну інструкцію, як-от прочитати символ зі стрічки, замінити його сумою значень двох прилеглих клітинок тощо. Джерело.
Машина Тюрінга здатна імітувати будь-який комп’ютерний алгоритм, а лямбда-обчислення Черча дає змогу імітувати будь-яку машину Тюрінга. Учитель і учень просто підійшли до одного й того ж питання з різних боків.
У чому різниця між функціональним програмуванням та іншими стилями програмування?
Найпряміший спосіб познайомитися з основними рисами функціонального програмування — порівняти декларативну парадигму з імперативними мовами і, зокрема, об’єктно-орієнтованим програмуванням.
З точки зору стилю програмування імперативні програми — це послідовності інструкцій, які ведуть до бажаного результату. Програма в декларативному стилі просто дуже докладно говорить, які результати потрібні.
Уявіть, що нам потрібно надіслати паперового листа Альберту. Ось як виглядали б інструкції для машини в імперативному стилі:
1. Візьми аркуш паперу і ручку он там. 2. Візьми конверт он там.
4. Склади аркуш навпіл. 3. Напиши "Привіт, Альберте!" на аркуші паперу.
5. Візьми конверт он там. 6. Напиши адресу Альберта на конверті.
8. Запечатай конверт. 7. Поклади аркуш паперу в конверт.
1. Візьми аркуш паперу і ручку он там. 2. Візьми конверт он там. 3. напиши "Привіт, Альберте!" на аркуші паперу. 4. Склади аркуш навпіл. 5. Візьми конверт он там. 6. Напиши адресу Альберта на конверті. 7. Поклади аркуш паперу в конверт. 8. Запечатай конверт.
Звучить виснажливо, але цілком зрозуміло, якщо машина знає адресу Альберта і слова, які ми використовуємо.
Аналогічне завдання функціональною мовою виглядало б якось так:
Лист — це запечатаний конверт з адресою Альберта з повідомленням усередині. Повідомлення — це аркуш паперу, на якому написаний текст. Текст: "Привіт, Альберте".
Людині така інструкція може здатися дивною і непослідовною, але компілятор, який перекладатиме ваш код на машинну мову, знає функції підписування, запечатування і всіх інших дій.
Об’єктно-орієнтоване програмування об’єднує дані та процедури з ними в об’єкти. Функціональне програмування розмежовує дані та функції.
Об’єктно-орієнтоване програмування об’єднує дані та процедури з ними в об’єкти. Функціональне програмування розмежовує дані та функції.
В об’єктно-орієнтованому програмуванні ви працюєте з об’єктами — структурами даних, у яких є вся потрібна машині інформація і процедури, які потрібно провести. У функціональному програмуванні ви працюєте з функціями — операціями над ввідними даними на кшталт додавання або віднімання. Важливо, що ці операції ніяк не пов’язані з даними, до яких вони застосовуються.
В об’єктно-орієнтованому програмуванні за допомогою методів можна присвоювати нові значення змінним. Функціональне програмування просто пов’язує вхідні дані з певними результатами. Значення змінних оголошуються один раз і більше не змінюються.
В об’єктно-орієнтованому програмуванні за допомогою методів можна присвоювати нові значення змінним. Функціональне програмування просто пов’язує вхідні дані з певними результатами. Значення змінних оголошуються один раз і більше не змінюються.
І в ООП, і в ФП є змінні . В ООП змінні по-справжньому змінні, тобто їхнє значення може змінюватися. У ФП змінні більше схожі на змінні в математиці, де х це — просто ім’я для конкретного значення, як х=2.
Оскільки в ООП значення змінних можуть змінюватися, машині потрібно виконувати інструкції в заданому порядку, щоб отримати бажаний результат. Функціональні мови дають змогу виконувати незалежні одна від одної інструкції в довільному порядку, тому що значення змінних не зміняться і не зможуть таким чином вплинути на кінцевий результат.
В ООП процедури можуть викликати побічні ефекти в нелокальних змінних. У ФП функції, як правило, не мають несподіваних побічних ефектів.
В ООП процедури можуть викликати побічні ефекти в нелокальних змінних. У ФП функції зазвичай не мають несподіваних побічних ефектів.
Якби інструкції з прикладу вище були виконані в іншому порядку, запрограмований робот міг би взяти порожній конверт і покласти його в скриньку, не підписуючи. Це було прикладом побічних ефектів. У функціональному програмуванні не буває побічних ефектів, якщо ви не закладете їх у програму спеціально.
Чому блокчейн-проекти використовують функціональні мови програмування?
Завдяки незмінності змінних у функціональних мовах простіше уникнути побічних ефектів, які можуть призвести до вразливостей і поломок. Дивлячись на функціональний код, розробник одразу побачить, що робить програма. Йому не потрібно брати до уваги контекст, у якому виконується програма, тому що контекст не вплине на те, що робить функція. Крім того, у функціональних мовах найчастіше закладені функції, які спрощують створення розподілених систем.
Чудовий приклад цих переваг — Erlang, функціональна мова програмування, розроблена Джо Армстронгом, Робертом Вірдінгом і Майком Вільямсом у 1986. Ця мова дає змогу розробникам оновлювати або інакше змінювати код у системі, що працює, "по-горячому", не зупиняючи систему. Erlang особливо підходить для блокчейн-розробки та створення відмовостійких систем.
Які функціональні мови найпопулярніші? Які з них використовуються в блокчейн-програмуванні?
Більшість сучасних мов програмування — мультипарадигменні. У них є властивості об’єктно-орієнтованих мов, функціональних мов та інших парадигм. Серед суто функціональних мов програмування найпредставленіші — Haskell та Elm. Популярні функціональні мови з елементами інших парадигм: OCaml, Erlang, Elixir, Scala, F#, Clojure, Scheme.
Блокчейн-проекти використовують деякі функціональні мови для створення блокчейн-протоколів і смарт-контрактів. Серед таких мов: Haskell, OCaml, Erlang, Sophia та Elixir.
Блокчейн-платформа для розподілених додатків і смарт-контрактів æternity використовує мови Erlang, Sophia і Elixir. Блокчейн-протокол написаний з нуля на Erlang, а для смарт-контрактів використовується спеціально розроблена для æternity функціональна мова Sophia. Elixir, похідну мову, схожу на Erlang, використовують для навчання нових розробників. До команди æternity входить один із творців Erlang Роберт Вірдінг, Ульф Норелл, Тобіас Ерік та інші експерти з сотнею років спільного досвіду в ФП.
Приєднатися до російськомовної спільноти проєкту:
Що розробнику децентралізованих додатків потрібно знати про функціональне програмування?
Людям, пов’язаним із блокчейн-розробкою, буде корисно знати основні принципи функціонального програмування. Це допоможе написати кращий код на мультипарадигменних мовах. Однак, щоб зрозуміти і правильно застосувати ці принципи, розробнику доведеться прийняти те, що називають функціональним ходом мислення.
Інший важливий момент — писати програми функціональними мовами безпечніше через відсутність побічних ефектів. Для математичних розрахунків і розподілених обчислень функціональний код може бути коротшим, ніж аналоги на мовах ООП. Крім того, деякі функціональні мови, наприклад, Erlang, дають змогу розробникам змінювати код "на ходу" без перезавантаження або вимкнення системи.
Будь-якому розробнику важливо знати принципи та переваги всіх парадигм програмування і розуміти, яка з них підходить у кожному окремому випадку. Переваги функціонального програмування підходять для розподілених обчислень і систем з високими вимогами до безпеки та відмовостійкості на кшталт телекомунікаційних і блокчейн-мереж.
Які перспективи функціонального програмування в блокчейні та розробці децентралізованих додатків?
Кожна з парадигм краще підходить для розв’язання певних проблем, тому найпросунутіші системи повинні використовувати різні мови для різних завдань. З іншого боку, настільки ж імовірно, що блокчейн-програмування буде більшою мірою спиратися на мультипарадигменні мови.
Блокчейн-індустрія поки тільки починає використовувати переваги функціональних мов програмування. У міру становлення цієї ніші більше проєктів використовуватимуть такі мови для побудови розподілених мереж.
Підписуйтесь на розсилку і не пропускайте нові спецпроєкти
Автор — Кшиштоф Шпак Редактор — Тетяна Оттер Дизайнерка та ілюстраторка — Зара Аракелян Проєктний менеджер — Костянтин Голубєв Керівник — Влад Ліхута