F# — багатопарадигмальна мова програмування, розроблена в підрозділі Microsoft Research і призначена для виконання на платформі Microsoft.NET. Вона поєднує в собі виразність функційних мов, таких як OCaml і Haskell, з можливостями і об'єктною моделлю .NET.
F# | |
---|---|
Парадигма | Парадигма програмування, Функційне програмування, Імперативне програмування, Об'єктно-орієнтоване програмування, Метапрограмування |
Дата появи | 2005 |
Творці | Microsoft Research, |
Розробник | Microsoft і d |
Останній реліз | 16.8 (10 листопада 2020)[1] |
Система типізації | статична, строга типізація і вивід типів |
Під впливом від | ML, OCaml, C#, Python, Haskell, Scala, Erlang |
Операційна система | кросплатформова програма |
Ліцензія | Apache License |
Звичайні розширення файлів | .fs , .fsi , .fsx або .fsscript |
Репозиторій вихідного коду | github.com/dotnet/fsharp |
Вебсайт | The F# Software Foundation |
|
Короткий огляд F#
Функційна мова максимально адаптована до використання в .NET Framework, відповідно, вона не заперечує і імперативного підходу.
Протягом тривалого часу F# існував як дослідницький проект, основним завданням якого було збагатити імперативну мову C# можливостями традиційно доступними лише функціональним мовам. Безліччю нововведень C# 3.0 з Visual Studio 2008 завдячує саме йому. Сам по собі F# не створений з чистого аркуша в Microsoft, в його основу покладено досить популярний OCaml, який, у свою чергу, походить від одної з перших типізованих функціональних мов ML. Попри те, що синтаксично F# і OCaml досить близькі, вони не еквівалентні: грубо кажучи, перший становить собою підмножину другого, доповнену доступом до властивостей .NET Framework. Однак деякі програми на OCaml можуть бути практично без модифікацій скомпільовані F#, зворотна компіляція також можлива, зрозуміло, за відсутності звернень до класів .NET Framework.
Історія
Історія F# почалася в 2002 році, коли команда розробників з Microsoft Research під керівництвом вирішила, що мови сімейства ML цілком підходять для реалізації функціональної парадигми на платформі .NET. Ідея розробки нової мови з'явилася під час роботи над Generic'ами — реалізацією узагальненого програмування для Common Language Runtime. Відомо, що у свій час як прототип нової мови розглядалася Haskell, але через функціональну чистоту і складнішу систему типів потенційний Haskell .NET не міг би надати розробникам простого механізму роботи з бібліотекою класів .NET Framework, а значить, не давав би якихось додаткових переваг. Як би там не було, за основу був узятий OCaml, мова з сімейства ML, яка не є чисто функціональною і надає можливості для імперативного і об'єктно-орієнтованого програмування. Haskell, хоч і не став безпосередньо батьком нової мови, тим не менше, справив на нього деякий вплив. Наприклад, концепція обчислювальних виразів (computation expressions або workflows), що грають важливу роль для асинхронного програмування та реалізації DSL на F#, запозичена з монад Haskell.
Наступним кроком у розвитку нової мови стала поява в 2005 році її першої версії. З тих пір навколо F# стало формуватися співтовариство. За рахунок підтримки функціональної парадигми мова виявилася потрібною в науковій сфері та фінансових організаціях. Багато в чому завдяки цьому Microsoft вирішила перевести F# зі статусу дослідницьких проектів у статус підтримуваних продуктів і поставити її в один ряд з основними мовами платформи .NET. І це попри те, що останнім часом все більшу активність проявляють динамічні мови, підтримка яких також присутня в .NET Framework. 12 квітня 2010 світ побачила нова версія флагманського продукту для розробників — Microsoft Visual Studio 2010, яка підтримує розробку на F# прямо з коробки.
Основні можливості мови
F# є багатопарадигмальною мовою, а це означає, що на ній можна реалізовувати функції вищих порядків, усередині яких виконувати імперативний код і обгортати все це в класи для використання клієнтами, написаними іншими мовами на платформі .NET.
F# функціональна
F#, будучи спадкоємцем традицій сімейства мов ML, надає повний набір інструментів функціонального програмування: тут є алгебричні типи даних і функції вищого порядку, можливість композиції функцій і незмінні структури даних, а також часткове застосування на пару з карруванням. Зі слів експертів в OCaml, в F# не вистачає функціональних обʼєктів.
Усі функціональні можливості F # реалізовані поверх загальної системи типів .NET Framework. Однак цей факт не забезпечує зручності використання таких конструкцій з інших мов платформи. При розробці власних бібліотек на F# слід передбачити створення об'єктно-орієнтованих обгорток, які буде простіше використовувати з C# або Visual Basic. NET.
F# імперативна
У випадках, коли багатих функціональних можливостей не вистачає, F # надає розробникові можливість використовувати в коді принади змінюваного стану. Це як безпосередньо змінювані змінні, підтримка полів і властивостей об'єктів стандартної бібліотеки, так і явні цикли, а також змінні колекції і типи даних.
F# об'єктно-орієнтована
Об'єктно-орієнтовані можливості F #, як і багато чого іншого в цій мові, обумовлені необхідністю надати розробникам можливість використовувати стандартну бібліотеку класів .NET Framework. З поставленим завданням мова цілком справляється: можна як використовувати бібліотеки класів, реалізовані на інших .NET мовах, так і розробляти свої власні. Слід зазначити, однак, що деякі можливості ГО мов реалізовані не самим звичним чином.
Таке змішання парадигм, з одного боку, може привести до плачевних результатів, а з іншого — надає більше гнучкості і дозволяє писати простіший код. Так, наприклад, всередині стандартної бібліотеки F# деякі функції написані в імперативному стилі з метою оптимізації швидкості виконання.
Томаш Петрічек у своєму блозі згадує також про «мовно-орієнтоване» програмування. F# відмінно підходить як для написання вбудованих DSL, тобто імітації предметної області засобами мови програмування, так і для перетворення F# коду в конструкції, виконувані іншими засобами, наприклад в SQL-вирази або в послідовності інструкцій GPU. Крім того, в комплект постачання F# входять утиліти FsYacc і FsLex, які є аналогами таких же утиліт для OCaml, і які дозволяють генерувати синтаксичні та лексичні аналізатори, а значить на F# цілком можна розробити свою власну мову програмування.
Розширені можливості
Обчислювальні вирази
Серед нововведень F# можна особливо виділити так звані обчислювальні вирази (computation expressions або workflows). Вони є узагальненням генераторів послідовностей і, зокрема, дозволяють вбудовувати в F# такі обчислювальні структури, як монади і моноїд. Також вони можуть бути застосовані для асинхронного програмування та створення DSL.
Обчислювальний вираз має форму блоку, що містить певний код на F# у фігурних дужках. Цьому блоку повинен передувати спеціальний об'єкт, який називається ще будівник (builder). Загальна форма наступна: builder {comp-expr}.
Приклад написання обчислювального виразу для роботи з послідовностями, дозволяє створювати та маніпулювати послідовностями в функціональному стилі:
let mySequence = seq { yield 1 yield 2 yield 3 }
Будівник визначає спосіб інтерпретації того коду, який вказаний у фігурних дужках. Сам код обчислення зовні майже не відрізняється від звичайного коду на F#, крім того, що в ньому не можна визначати нові типи, а також не можна використовувати змінні. Замість таких значень можна використовувати посилання, але робити це слід з великою обережністю, оскільки обчислювальні вирази зазвичай створюю відкладені обчислення, а останні не дуже люблять побічні ефекти.
У залежності від будівника всередині обчислювального виразу можна використовувати особливі конструкції let!, Use!, Return, return!, Yield і yield!. Якщо читач знайомий з мовою програмування Haskell, то можна помітити, що let! відповідає стрілкою з нотації do, а return має той же зміст, що і в Haskell.
За своєю суттю обчислювальне вираз є синтаксичним цукром навколо зазначеного будівника. Компілятор F# проходиться по коду і замінює мовні конструкції викликами відповідних методів будівника b згідно з наступною таблицею:
Конструкція | Форма перетворення |
---|---|
let pat = expr in cexpr | let pat = expr in cexpr |
let! pat = expr in cexpr | b.Bind(expr, (fun pat -> cexpr)) |
return expr | b.Return(expr) |
return! expr | b.ReturnFrom(expr) |
yield expr | b.Yield(expr) |
yield! expr | b.YieldFrom(expr) |
use pat = expr in cexpr | b.Using(expr, (fun pat -> cexpr)) |
use! pat = expr in cexpr | b.Bind(expr, (fun x -> b.Using(x, fun pat -> cexpr)) |
do! expr in cexpr | b.Bind(expr, (fun () -> cexpr)) |
for pat in expr do cexpr | b.For(expr, (fun pat -> cexpr)) |
while expr do cexpr | b.While((fun () -> expr), b.Delay( fun () -> cexpr)) |
if expr then cexpr1 else cexpr2 | if expr then cexpr1 else cexpr2 |
if expr then cexpr | if expr then cexpr else b.Zero() |
cexpr1
| b.Combine(cexpr1, b.Delay(fun () -> cexpr2)) |
try cexpr with patn -> cexprn | b.TryWith(expr, fun v -> match v with (patn:ext) -> cexprn | _ raise exn) |
try cexpr finally expr | b.TryFinally(cexpr, (fun () -> expr)) |
Основна ідея полягає в тому, що коли компілятор обробляє конструкцію обчислювального виразу, то він намагається викликати відповідний метод будівника. Будівник не зобов'язаний реалізовувати всі вказані методи. Якщо потрібного методу немає, то буде згенерована помилка компіляції.
Асинхронні потоки операцій (async workflows)
Асинхронні потоки операцій — це один з найцікавіших прикладів практичного використання обчислювальних виразів. Код, що виконує будь-які неблокуючі операції введення-виведення, як правило складний для розуміння, оскільки представляє з себе безліч callback-методів, кожен з яких обробляє якийсь проміжний результат і можливо починає нову асинхронну операцію. Асинхронні потоки операцій дозволяють писати асинхронний код послідовно, не визначаючи callback-методи явно. Для створення асинхронного потоку операцій використовується блок async:
open System.IO open System.Net open Microsoft.FSharp.Control.WebExtensions let getPage (url: string) = async {let req = WebRequest.Create (url) let! res = req.AsyncGetResponse () use stream = res.GetResponseStream () use reader = new StreamReader (stream) let! result = reader.AsyncReadToEnd () return result
Тут ми оголосили функцію getPage, яка повинна повертати вміст сторінки за заданою адресою. Ця функція має тип string--> Async <string> і повертає асинхронну операцію, яка може бути використана для отримання рядка з вмістом сторінки. Варто відзначити, що класи WebRequest і StreamReader не мають методів AsyncGetResponse і AsyncReadToEnd, це методи розширення.
Будівник асинхронного потоку операцій, працює таким чином. Зустрівши оператор let! або do!, він починає виконувати операцію асинхронно, при цьому метод, початківець асинхронну операцію, отримає частину, що залишилася блоку async як функція зворотного виклику. Після завершення асинхронної операції переданий callback продовжить виконання асинхронного потоку операцій, але, можливо, вже в іншому потоці операційної системи (для виконання коду використовується пул потоків). У результаті код виглядає так, як ніби він виконується послідовно. Те, що може бути з легкістю записано всередині блоку async з використанням циклів і умовних операторів, досить складно реалізується з використанням звичайної техніки, що вимагає опису множини callback-методів і передачею стану між їх викликами.
Обробка винятків — найбільш наочний приклад зручності асинхронних потоків операцій. Якщо ми пишемо асинхронний код у традиційному стилі, то кожен метод зворотного виклику повинен обробляти винятки самостійно. Блок async може включати оператор try, за допомогою якого можна обробляти винятки.
_ as e--> printfn "error:% s" e.Message return None
У цьому прикладі потік операцій повертає значення типу string ~ option, тобто, або рядок або пусте значення, щоб викликає код міг обробити помилку.
Значення типу Async <_> потрібно передати в один із статичних методів класу Async, щоб розпочати виконання відповідного потоку операцій. У найпростішому випадку можна скористатися методом Async.RunSynchronously, який просто заблокує викликає потік до тих пір, поки всі операції не будуть виконані.
MailboxProcessor
MailboxProcessor — це клас зі стандартної бібліотеки F #, реалізує один з патернів паралельного програмування. MailboxProcessor є агентом23, обробляють чергу повідомлень, які поставляються йому ззовні за допомогою методу Post. Вся конкурентність підтримується реалізацією класу, який містить чергу з можливістю одночасного запису кількома письменниками і читання одним єдиним читачем, яким є сам агент.
let agent = MailboxProcessor.Start (fun inbox--> async {while true do let! msg = inbox.Receive () printfn "message received: '% s'" msg})
Вище наведена реалізація найпростішого агента, який при отриманні повідомлення, що містить рядок, виводить його на екран. Послати агенту повідомлення, як вже було сказано вище, можна за допомогою методу Post:
agent.Post ("Hello world!")
Цікаво відзначити тип функції, що є єдиним параметром конструктора агента (і статичного методу Start) 24:
static member Start: (MailboxProcessor <'Msg>--> Async <unit>)--> MailboxProcessor <' Msg>
З цього визначення видно, що основною «робочою конячкою» агента є функція, на вхід отримує примірник самого агента і повертає асинхронну операцію, про які йшлося трохи вище.
Природно, що пряме відповідність агентів і потоков25 було б не дуже зручно і вкрай неефективно, тому що сильно обмежувало б кількість одночасно працюючих агентів. Завдяки використанню асинхронних потоків операцій, агент більшу частину часу є просто структурою в пам'яті, яка містить деякий внутрішній стан і тільки в ті моменти, коли в чергу надходить чергове повідомлення, функція обробки реєструється для виконання в потоці з системного пулу. Функцією обробки якраз і є та, що була передана в конструктор або метод Start. Таким чином, весь внутрішній стан агента підтримується інфраструктурою, а не лягає тяжким вантажем на плечі користувача. Для підтвердження цього факту можна спробувати створити кілька тисяч агентів, запустити їх і почати випадковим чином відправляти їм повідомлення.
Обробка подій
Спочатку. NET дозволяє обробляти події по одному. Обробником події є функція, яка викликається щоразу з деякими аргументами, і якщо розробнику необхідно зберігати якесь додаткове стан між викликами подій — це доводиться робити самостійно. Крім того, оригінальна модель підписки може призводити до витоку пам'яті через наявність неявних взаємних посилань у передплатника і генераторі подій.
F #, звичайно, дозволяє працювати з подіями в класичному розумінні. Правда, робиться це за допомогою трохи незвичайного синтаксису: замість використання операторів + = і -= для реєстрації і деактивації обробника події використовується пара методів Add / Remove. button.Click.Add (fun args--> printfn «Button clicked»)
З іншого боку, F # дозволяє маніпулювати потоками подій, і працювати з ними як з послідовностями, використовуючи функції filter, map, split та інші. Наприклад, наступний код фільтрує потік подій натискання клавіш всередині поля введення, вибираючи лише ті з них, які були натиснуті в поєднанні з Ctrl, після чого, з усіх аргументів подій вибираються тільки значення поля KeyCode. Таким чином, значенням keyCodes буде потік подій, які містять лише коди клавіш, натиснутих з дзвінком Ctrl.
> Event.map (fun args--> args.KeyCode)
Варто відзначити, що обробка потоків подій дозволяє розробнику не піклуватися про тонкощі відписки, а просто генерувати нові потоки подій на основі вже існуючих, використовувати ці потоки як значення, тобто передавати їх як аргументи та повертати з функцій.
Використання подібної техніки може призвести до значного спрощення коду для реалізації, наприклад, функціональності Drag & Drop. Адже це є ні що інше, як композиція події натискання кнопки миші, переміщення курсору з натиснутою кнопкою і потім відпускання. Для прикладу частину, що відповідає за drag, можна легко перекласти з російської на F #:
> Event.merge form.MouseMove
Поєднання обробки потоків подій з асинхронними потоками операцій дозволяє також досить просто вирішувати сумно відому проблему GUI-додатків, коли обробник події графічного компоненту повинен виконуватись в основному потоці і будь-яке зволікання призведе до «зависання» інтерфейсу додатку.
Приклади використання
Існує цікавий приклад використання quotations в F# як засобу мета-програмування. Завдання пов'язана з масивної паралельною обробкою даних за допомогою спеціальної бібліотеки або на багатоядерній процесорній системі x64, або на графічному процесорі GPU. Визначається невелика підмножина F#, код з якої може бути відтранслюваним і запущеним на цільовій платформі. Це дозволяє писати «звичайні» функції на F#, налагоджувати їх стандартним чином, а потім за допомогою механізму quotations обробляти ці функції і запускати на GPU. Більш того, програма на F# може створювати «на льоту» такі функції, які вже потім можуть відтранслюватися і запуститися на іншій платформі. Примітно, що при реалізації такої трансляції широко використовується спеціальна можливість F # у вигляді активного зіставлення зі зразком (active pattern matching), яка помітно спрощує написання транслятора.
Мова F# може бути зручна для створення DSL, які стають частиною самого F#, причому такі мови можуть бути досить короткими і виразними. Наприклад, у книзі Real-World Functional Programming наводиться бібліотека для опису анімації. Первісна ідея була реалізована в проекті Fran [Elliot, Hudak, 1997] на мові Haskell. Опис ідеї ще можна знайти в книзі The Haskell School of Expression [6]. Анімація моделюється як залежна від часу величина. На основі примітивів будуються вже складові лексикон предметної області функції, за допомогою яких можна описувати досить складні анімації і робити це декларативно. Що стосується реалізації, то там багато спільного з монадами.
Ось приклад того, як виглядає на мові F# визначення анімованої частини сонячної системи, яку потім можна візуалізувати на екрані комп'ютера:
let solarSystem = sun - (rotate 80.00f 4.1f mercury) - (rotate 150.0f 1.6f venus) - (rotate 215.0f 1.0f (earth - (rotate 20.0f 12.0f moon)))
Наступним прикладом використання F# є комерційний продукт WebSharper фірми IntelliFactory [2]. Це платформа для створення клієнтських web-додатків. Вона дозволяє писати клієнтський код на F#, який потім буде відтранслювати на JavaScript. Така трансляція поширюється на достатню велику підмножину F #, включаючи функціональне ядро мови, алгебричні типи даних, класи, об'єкти, винятки й делегати. Також підтримується значна частина стандартної бібліотеки F #, включаючи роботу з послідовностями (sequences), подіями і асинхронними обчислювальними виразами (async workflows). Все може бути автоматично відтранслювати на цільову мову JavaScript. Крім того, підтримується деяка частина стандартних класів самого. NET, і обсяг підтримки буде зростати.
Цей продукт примітний тим, що тут використовується цілий ряд прийомів, характерних для функціонального програмування. Так, в WebSharper вбудований DSL для завдання HTML-коду, в якому широко застосовуються комбінатори.
Наприклад, наступний шматок коду на F #:
Div [Class «Header»] — <[H1 ["Our Website"] Br [] P ["Hello, world!"] Img [Src "smile.jpg"]]
буде перетворений на виході в такий код HTML:
<div class="header"> <h1> Our Website </h1> <br /> <p> Hello, world! </p> <img src="smile.jpg" /> </div>
Для самої ж трансляції в JavaScript використовуються цитування. Код для трансляції повинен бути помічений атрибутом JavaScriptAttribute, успадкованим від стандартного ReflectedDefinitionAttribute.
{{{1}}}
Висновок
Відповідно до гіпотези лінгвістичної відносності, люди, що говорять на різних мовах, мислять і сприймають навколишню дійсність по-різному. Якщо припустити, мова програмування, яку використовує програміст, впливає на те, як він бачить вирішення проблеми, то не можна не визнати, що F # буде підштовхувати його до пошуку простіших і елегантніших рішень.
Без сумніву, F # знайде широке застосування у фінансовій сфері та в галузі статистики. Крім цього, F # заслуговує на те, щоб стати досить популярним у інших областях, хоча б тому, що робить багатопотокове програмування простішим і зрозумілішим.
Слід також зазначити, що зараз F # є, мабуть, єдиною функціональною мовою програмування, яка просувається одним з провідних виробників у галузі розробки програмного забезпечення. Він дозволяє використовувати безліч вже існуючих бібліотек, писати програми для різних платформ і, що не менш важливо, робити все це в сучасній IDE.
Примітки
- Release 16.8 — 2020.
Література
- IntelliFactory’s WebSharper [ 16 грудня 2010 у Wayback Machine.].
- Лекції Джона Харрисона «Introduction to Functional Programming». Російський переклад [ 30 листопада 2010 у Wayback Machine.].
- Список проектів що використовують F# з відкритим кодом: http://stackoverflow.com/questions/383848/f-open-source-projects [ 16 червня 2010 у Wayback Machine.].
- Jon Harrop. F# for Scientists. Wiley-Interscience, New York, NY, USA, 2008.
- Paul Hudak. The Haskell School of Expression: Learning Functional Programming through Multimedia. Cambridge University Press, 2000.
- Petricek. Accelerator and F#[недоступне посилання з червня 2019].
- .
- Блог Томаша Петрічека [ 27 грудня 2010 у Wayback Machine.]
- Tomas Petricek and Jon Skeet. Real-World Functional Programming with examples in F# and C#. Manning Publications, 2009.
Ця стаття містить правописні, лексичні, граматичні, стилістичні або інші мовні помилки, які треба виправити. (липень 2017) |
Це незавершена стаття про мови програмування. Ви можете проєкту, виправивши або дописавши її. |
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
F bagatoparadigmalna mova programuvannya rozroblena v pidrozdili Microsoft Research i priznachena dlya vikonannya na platformi Microsoft NET Vona poyednuye v sobi viraznist funkcijnih mov takih yak OCaml i Haskell z mozhlivostyami i ob yektnoyu modellyu NET F ParadigmaParadigma programuvannya Funkcijne programuvannya Imperativne programuvannya Ob yektno oriyentovane programuvannya MetaprogramuvannyaData poyavi2005TvorciMicrosoft Research RozrobnikMicrosoft i dOstannij reliz16 8 10 listopada 2020 1 Sistema tipizaciyistatichna stroga tipizaciya i vivid tipivPid vplivom vidML OCaml C Python Haskell Scala ErlangOperacijna sistemakrosplatformova programaLicenziyaApache LicenseZvichajni rozshirennya fajliv fs fsi fsx abo fsscriptRepozitorij vihidnogo kodugithub com dotnet fsharpVebsajtThe F Software Foundation Mediafajli u VikishovishiKorotkij oglyad F Funkcijna mova maksimalno adaptovana do vikoristannya v NET Framework vidpovidno vona ne zaperechuye i imperativnogo pidhodu Protyagom trivalogo chasu F isnuvav yak doslidnickij proekt osnovnim zavdannyam yakogo bulo zbagatiti imperativnu movu C mozhlivostyami tradicijno dostupnimi lishe funkcionalnim movam Bezlichchyu novovveden C 3 0 z Visual Studio 2008 zavdyachuye same jomu Sam po sobi F ne stvorenij z chistogo arkusha v Microsoft v jogo osnovu pokladeno dosit populyarnij OCaml yakij u svoyu chergu pohodit vid odnoyi z pershih tipizovanih funkcionalnih mov ML Popri te sho sintaksichno F i OCaml dosit blizki voni ne ekvivalentni grubo kazhuchi pershij stanovit soboyu pidmnozhinu drugogo dopovnenu dostupom do vlastivostej NET Framework Odnak deyaki programi na OCaml mozhut buti praktichno bez modifikacij skompilovani F zvorotna kompilyaciya takozh mozhliva zrozumilo za vidsutnosti zvernen do klasiv NET Framework IstoriyaIstoriya F pochalasya v 2002 roci koli komanda rozrobnikiv z Microsoft Research pid kerivnictvom virishila sho movi simejstva ML cilkom pidhodyat dlya realizaciyi funkcionalnoyi paradigmi na platformi NET Ideya rozrobki novoyi movi z yavilasya pid chas roboti nad Generic ami realizaciyeyu uzagalnenogo programuvannya dlya Common Language Runtime Vidomo sho u svij chas yak prototip novoyi movi rozglyadalasya Haskell ale cherez funkcionalnu chistotu i skladnishu sistemu tipiv potencijnij Haskell NET ne mig bi nadati rozrobnikam prostogo mehanizmu roboti z bibliotekoyu klasiv NET Framework a znachit ne davav bi yakihos dodatkovih perevag Yak bi tam ne bulo za osnovu buv uzyatij OCaml mova z simejstva ML yaka ne ye chisto funkcionalnoyu i nadaye mozhlivosti dlya imperativnogo i ob yektno oriyentovanogo programuvannya Haskell hoch i ne stav bezposeredno batkom novoyi movi tim ne menshe spraviv na nogo deyakij vpliv Napriklad koncepciya obchislyuvalnih viraziv computation expressions abo workflows sho grayut vazhlivu rol dlya asinhronnogo programuvannya ta realizaciyi DSL na F zapozichena z monad Haskell Nastupnim krokom u rozvitku novoyi movi stala poyava v 2005 roci yiyi pershoyi versiyi Z tih pir navkolo F stalo formuvatisya spivtovaristvo Za rahunok pidtrimki funkcionalnoyi paradigmi mova viyavilasya potribnoyu v naukovij sferi ta finansovih organizaciyah Bagato v chomu zavdyaki comu Microsoft virishila perevesti F zi statusu doslidnickih proektiv u status pidtrimuvanih produktiv i postaviti yiyi v odin ryad z osnovnimi movami platformi NET I ce popri te sho ostannim chasom vse bilshu aktivnist proyavlyayut dinamichni movi pidtrimka yakih takozh prisutnya v NET Framework 12 kvitnya 2010 svit pobachila nova versiya flagmanskogo produktu dlya rozrobnikiv Microsoft Visual Studio 2010 yaka pidtrimuye rozrobku na F pryamo z korobki Osnovni mozhlivosti moviF ye bagatoparadigmalnoyu movoyu a ce oznachaye sho na nij mozhna realizovuvati funkciyi vishih poryadkiv useredini yakih vikonuvati imperativnij kod i obgortati vse ce v klasi dlya vikoristannya kliyentami napisanimi inshimi movami na platformi NET F funkcionalna F buduchi spadkoyemcem tradicij simejstva mov ML nadaye povnij nabir instrumentiv funkcionalnogo programuvannya tut ye algebrichni tipi danih i funkciyi vishogo poryadku mozhlivist kompoziciyi funkcij i nezminni strukturi danih a takozh chastkove zastosuvannya na paru z karruvannyam Zi sliv ekspertiv v OCaml v F ne vistachaye funkcionalnih obʼyektiv Usi funkcionalni mozhlivosti F realizovani poverh zagalnoyi sistemi tipiv NET Framework Odnak cej fakt ne zabezpechuye zruchnosti vikoristannya takih konstrukcij z inshih mov platformi Pri rozrobci vlasnih bibliotek na F slid peredbachiti stvorennya ob yektno oriyentovanih obgortok yaki bude prostishe vikoristovuvati z C abo Visual Basic NET F imperativna U vipadkah koli bagatih funkcionalnih mozhlivostej ne vistachaye F nadaye rozrobnikovi mozhlivist vikoristovuvati v kodi prinadi zminyuvanogo stanu Ce yak bezposeredno zminyuvani zminni pidtrimka poliv i vlastivostej ob yektiv standartnoyi biblioteki tak i yavni cikli a takozh zminni kolekciyi i tipi danih F ob yektno oriyentovana Ob yektno oriyentovani mozhlivosti F yak i bagato chogo inshogo v cij movi obumovleni neobhidnistyu nadati rozrobnikam mozhlivist vikoristovuvati standartnu biblioteku klasiv NET Framework Z postavlenim zavdannyam mova cilkom spravlyayetsya mozhna yak vikoristovuvati biblioteki klasiv realizovani na inshih NET movah tak i rozroblyati svoyi vlasni Slid zaznachiti odnak sho deyaki mozhlivosti GO mov realizovani ne samim zvichnim chinom Take zmishannya paradigm z odnogo boku mozhe privesti do plachevnih rezultativ a z inshogo nadaye bilshe gnuchkosti i dozvolyaye pisati prostishij kod Tak napriklad vseredini standartnoyi biblioteki F deyaki funkciyi napisani v imperativnomu stili z metoyu optimizaciyi shvidkosti vikonannya Tomash Petrichek u svoyemu blozi zgaduye takozh pro movno oriyentovane programuvannya F vidminno pidhodit yak dlya napisannya vbudovanih DSL tobto imitaciyi predmetnoyi oblasti zasobami movi programuvannya tak i dlya peretvorennya F kodu v konstrukciyi vikonuvani inshimi zasobami napriklad v SQL virazi abo v poslidovnosti instrukcij GPU Krim togo v komplekt postachannya F vhodyat utiliti FsYacc i FsLex yaki ye analogami takih zhe utilit dlya OCaml i yaki dozvolyayut generuvati sintaksichni ta leksichni analizatori a znachit na F cilkom mozhna rozrobiti svoyu vlasnu movu programuvannya Rozshireni mozhlivostiObchislyuvalni virazi Sered novovveden F mozhna osoblivo vidiliti tak zvani obchislyuvalni virazi computation expressions abo workflows Voni ye uzagalnennyam generatoriv poslidovnostej i zokrema dozvolyayut vbudovuvati v F taki obchislyuvalni strukturi yak monadi i monoyid Takozh voni mozhut buti zastosovani dlya asinhronnogo programuvannya ta stvorennya DSL Obchislyuvalnij viraz maye formu bloku sho mistit pevnij kod na F u figurnih duzhkah Comu bloku povinen pereduvati specialnij ob yekt yakij nazivayetsya she budivnik builder Zagalna forma nastupna builder comp expr Priklad napisannya obchislyuvalnogo virazu dlya roboti z poslidovnostyami dozvolyaye stvoryuvati ta manipulyuvati poslidovnostyami v funkcionalnomu stili let mySequence seq yield 1 yield 2 yield 3 Budivnik viznachaye sposib interpretaciyi togo kodu yakij vkazanij u figurnih duzhkah Sam kod obchislennya zovni majzhe ne vidriznyayetsya vid zvichajnogo kodu na F krim togo sho v nomu ne mozhna viznachati novi tipi a takozh ne mozhna vikoristovuvati zminni Zamist takih znachen mozhna vikoristovuvati posilannya ale robiti ce slid z velikoyu oberezhnistyu oskilki obchislyuvalni virazi zazvichaj stvoryuyu vidkladeni obchislennya a ostanni ne duzhe lyublyat pobichni efekti U zalezhnosti vid budivnika vseredini obchislyuvalnogo virazu mozhna vikoristovuvati osoblivi konstrukciyi let Use Return return Yield i yield Yaksho chitach znajomij z movoyu programuvannya Haskell to mozhna pomititi sho let vidpovidaye strilkoyu z notaciyi do a return maye toj zhe zmist sho i v Haskell Za svoyeyu suttyu obchislyuvalne viraz ye sintaksichnim cukrom navkolo zaznachenogo budivnika Kompilyator F prohoditsya po kodu i zaminyuye movni konstrukciyi viklikami vidpovidnih metodiv budivnika b zgidno z nastupnoyu tabliceyu Konstrukciya Forma peretvorennya let i pat i i expr i in i cexpr i let i pat i i expr i in i cexpr i let i pat i i expr i in i cexpr i b Bind i expr i fun i pat i gt i cexpr i return i expr i b Return i expr i return i expr i b ReturnFrom i expr i yield i expr i b Yield i expr i yield i expr i b YieldFrom i expr i use i pat i i expr i in i cexpr i b Using i expr i fun i pat i gt i cexpr i use i pat i i expr i in i cexpr i b Bind i expr i fun x gt b Using x fun i pat i gt i cexpr i do i expr i in i cexpr i b Bind i expr i fun gt i cexpr i for i pat i in i expr i do i cexpr i b For i expr i fun i pat i gt i cexpr i while i expr i do i cexpr i b While fun gt i expr i b Delay fun gt i cexpr i if i expr i then i cexpr1 i else i cexpr2 i if i expr i then i cexpr1 i else i cexpr2 i if i expr i then i cexpr i if i expr i then i cexpr i else b Zero i cexpr1 i i cexpr2 i b Combine i cexpr1 i b Delay fun gt i cexpr2 i try i cexpr i with i patn i gt i cexprn i b TryWith i expr i fun v gt match v with i patn ext i gt i cexprn i raise exn i try i cexpr i finally i expr b TryFinally i cexpr i fun gt i expr i Osnovna ideya polyagaye v tomu sho koli kompilyator obroblyaye konstrukciyu obchislyuvalnogo virazu to vin namagayetsya viklikati vidpovidnij metod budivnika Budivnik ne zobov yazanij realizovuvati vsi vkazani metodi Yaksho potribnogo metodu nemaye to bude zgenerovana pomilka kompilyaciyi Asinhronni potoki operacij async workflows Asinhronni potoki operacij ce odin z najcikavishih prikladiv praktichnogo vikoristannya obchislyuvalnih viraziv Kod sho vikonuye bud yaki neblokuyuchi operaciyi vvedennya vivedennya yak pravilo skladnij dlya rozuminnya oskilki predstavlyaye z sebe bezlich callback metodiv kozhen z yakih obroblyaye yakijs promizhnij rezultat i mozhlivo pochinaye novu asinhronnu operaciyu Asinhronni potoki operacij dozvolyayut pisati asinhronnij kod poslidovno ne viznachayuchi callback metodi yavno Dlya stvorennya asinhronnogo potoku operacij vikoristovuyetsya blok async open System IO open System Net open Microsoft FSharp Control WebExtensions let getPage url string async let req WebRequest Create url let res req AsyncGetResponse use stream res GetResponseStream use reader new StreamReader stream let result reader AsyncReadToEnd return result Tut mi ogolosili funkciyu getPage yaka povinna povertati vmist storinki za zadanoyu adresoyu Cya funkciya maye tip string gt Async lt string gt i povertaye asinhronnu operaciyu yaka mozhe buti vikoristana dlya otrimannya ryadka z vmistom storinki Varto vidznachiti sho klasi WebRequest i StreamReader ne mayut metodiv AsyncGetResponse i AsyncReadToEnd ce metodi rozshirennya Budivnik asinhronnogo potoku operacij pracyuye takim chinom Zustrivshi operator let abo do vin pochinaye vikonuvati operaciyu asinhronno pri comu metod pochatkivec asinhronnu operaciyu otrimaye chastinu sho zalishilasya bloku async yak funkciya zvorotnogo vikliku Pislya zavershennya asinhronnoyi operaciyi peredanij callback prodovzhit vikonannya asinhronnogo potoku operacij ale mozhlivo vzhe v inshomu potoci operacijnoyi sistemi dlya vikonannya kodu vikoristovuyetsya pul potokiv U rezultati kod viglyadaye tak yak nibi vin vikonuyetsya poslidovno Te sho mozhe buti z legkistyu zapisano vseredini bloku async z vikoristannyam cikliv i umovnih operatoriv dosit skladno realizuyetsya z vikoristannyam zvichajnoyi tehniki sho vimagaye opisu mnozhini callback metodiv i peredacheyu stanu mizh yih viklikami Obrobka vinyatkiv najbilsh naochnij priklad zruchnosti asinhronnih potokiv operacij Yaksho mi pishemo asinhronnij kod u tradicijnomu stili to kozhen metod zvorotnogo vikliku povinen obroblyati vinyatki samostijno Blok async mozhe vklyuchati operator try za dopomogoyu yakogo mozhna obroblyati vinyatki as e gt printfn error s e Message return None U comu prikladi potik operacij povertaye znachennya tipu string option tobto abo ryadok abo puste znachennya shob viklikaye kod mig obrobiti pomilku Znachennya tipu Async lt gt potribno peredati v odin iz statichnih metodiv klasu Async shob rozpochati vikonannya vidpovidnogo potoku operacij U najprostishomu vipadku mozhna skoristatisya metodom Async RunSynchronously yakij prosto zablokuye viklikaye potik do tih pir poki vsi operaciyi ne budut vikonani MailboxProcessor MailboxProcessor ce klas zi standartnoyi biblioteki F realizuye odin z paterniv paralelnogo programuvannya MailboxProcessor ye agentom23 obroblyayut chergu povidomlen yaki postavlyayutsya jomu zzovni za dopomogoyu metodu Post Vsya konkurentnist pidtrimuyetsya realizaciyeyu klasu yakij mistit chergu z mozhlivistyu odnochasnogo zapisu kilkoma pismennikami i chitannya odnim yedinim chitachem yakim ye sam agent let agent MailboxProcessor Start fun inbox gt async while true do let msg inbox Receive printfn message received s msg Vishe navedena realizaciya najprostishogo agenta yakij pri otrimanni povidomlennya sho mistit ryadok vivodit jogo na ekran Poslati agentu povidomlennya yak vzhe bulo skazano vishe mozhna za dopomogoyu metodu Post agent Post Hello world Cikavo vidznachiti tip funkciyi sho ye yedinim parametrom konstruktora agenta i statichnogo metodu Start 24 static member Start MailboxProcessor lt Msg gt gt Async lt unit gt gt MailboxProcessor lt Msg gt Z cogo viznachennya vidno sho osnovnoyu robochoyu konyachkoyu agenta ye funkciya na vhid otrimuye primirnik samogo agenta i povertaye asinhronnu operaciyu pro yaki jshlosya trohi vishe Prirodno sho pryame vidpovidnist agentiv i potokov25 bulo b ne duzhe zruchno i vkraj neefektivno tomu sho silno obmezhuvalo b kilkist odnochasno pracyuyuchih agentiv Zavdyaki vikoristannyu asinhronnih potokiv operacij agent bilshu chastinu chasu ye prosto strukturoyu v pam yati yaka mistit deyakij vnutrishnij stan i tilki v ti momenti koli v chergu nadhodit chergove povidomlennya funkciya obrobki reyestruyetsya dlya vikonannya v potoci z sistemnogo pulu Funkciyeyu obrobki yakraz i ye ta sho bula peredana v konstruktor abo metod Start Takim chinom ves vnutrishnij stan agenta pidtrimuyetsya infrastrukturoyu a ne lyagaye tyazhkim vantazhem na plechi koristuvacha Dlya pidtverdzhennya cogo faktu mozhna sprobuvati stvoriti kilka tisyach agentiv zapustiti yih i pochati vipadkovim chinom vidpravlyati yim povidomlennya Obrobka podij Spochatku NET dozvolyaye obroblyati podiyi po odnomu Obrobnikom podiyi ye funkciya yaka viklikayetsya shorazu z deyakimi argumentami i yaksho rozrobniku neobhidno zberigati yakes dodatkove stan mizh viklikami podij ce dovoditsya robiti samostijno Krim togo originalna model pidpiski mozhe prizvoditi do vitoku pam yati cherez nayavnist neyavnih vzayemnih posilan u peredplatnika i generatori podij F zvichajno dozvolyaye pracyuvati z podiyami v klasichnomu rozuminni Pravda robitsya ce za dopomogoyu trohi nezvichajnogo sintaksisu zamist vikoristannya operatoriv i dlya reyestraciyi i deaktivaciyi obrobnika podiyi vikoristovuyetsya para metodiv Add Remove button Click Add fun args gt printfn Button clicked Z inshogo boku F dozvolyaye manipulyuvati potokami podij i pracyuvati z nimi yak z poslidovnostyami vikoristovuyuchi funkciyi filter map split ta inshi Napriklad nastupnij kod filtruye potik podij natiskannya klavish vseredini polya vvedennya vibirayuchi lishe ti z nih yaki buli natisnuti v poyednanni z Ctrl pislya chogo z usih argumentiv podij vibirayutsya tilki znachennya polya KeyCode Takim chinom znachennyam keyCodes bude potik podij yaki mistyat lishe kodi klavish natisnutih z dzvinkom Ctrl gt Event map fun args gt args KeyCode Varto vidznachiti sho obrobka potokiv podij dozvolyaye rozrobniku ne pikluvatisya pro tonkoshi vidpiski a prosto generuvati novi potoki podij na osnovi vzhe isnuyuchih vikoristovuvati ci potoki yak znachennya tobto peredavati yih yak argumenti ta povertati z funkcij Vikoristannya podibnoyi tehniki mozhe prizvesti do znachnogo sproshennya kodu dlya realizaciyi napriklad funkcionalnosti Drag amp Drop Adzhe ce ye ni sho inshe yak kompoziciya podiyi natiskannya knopki mishi peremishennya kursoru z natisnutoyu knopkoyu i potim vidpuskannya Dlya prikladu chastinu sho vidpovidaye za drag mozhna legko pereklasti z rosijskoyi na F gt Event merge form MouseMove Poyednannya obrobki potokiv podij z asinhronnimi potokami operacij dozvolyaye takozh dosit prosto virishuvati sumno vidomu problemu GUI dodatkiv koli obrobnik podiyi grafichnogo komponentu povinen vikonuvatis v osnovnomu potoci i bud yake zvolikannya prizvede do zavisannya interfejsu dodatku Prikladi vikoristannyaIsnuye cikavij priklad vikoristannya quotations v F yak zasobu meta programuvannya Zavdannya pov yazana z masivnoyi paralelnoyu obrobkoyu danih za dopomogoyu specialnoyi biblioteki abo na bagatoyadernij procesornij sistemi x64 abo na grafichnomu procesori GPU Viznachayetsya nevelika pidmnozhina F kod z yakoyi mozhe buti vidtranslyuvanim i zapushenim na cilovij platformi Ce dozvolyaye pisati zvichajni funkciyi na F nalagodzhuvati yih standartnim chinom a potim za dopomogoyu mehanizmu quotations obroblyati ci funkciyi i zapuskati na GPU Bilsh togo programa na F mozhe stvoryuvati na lotu taki funkciyi yaki vzhe potim mozhut vidtranslyuvatisya i zapustitisya na inshij platformi Primitno sho pri realizaciyi takoyi translyaciyi shiroko vikoristovuyetsya specialna mozhlivist F u viglyadi aktivnogo zistavlennya zi zrazkom active pattern matching yaka pomitno sproshuye napisannya translyatora Mova F mozhe buti zruchna dlya stvorennya DSL yaki stayut chastinoyu samogo F prichomu taki movi mozhut buti dosit korotkimi i viraznimi Napriklad u knizi Real World Functional Programming navoditsya biblioteka dlya opisu animaciyi Pervisna ideya bula realizovana v proekti Fran Elliot Hudak 1997 na movi Haskell Opis ideyi she mozhna znajti v knizi The Haskell School of Expression 6 Animaciya modelyuyetsya yak zalezhna vid chasu velichina Na osnovi primitiviv buduyutsya vzhe skladovi leksikon predmetnoyi oblasti funkciyi za dopomogoyu yakih mozhna opisuvati dosit skladni animaciyi i robiti ce deklarativno Sho stosuyetsya realizaciyi to tam bagato spilnogo z monadami Os priklad togo yak viglyadaye na movi F viznachennya animovanoyi chastini sonyachnoyi sistemi yaku potim mozhna vizualizuvati na ekrani komp yutera let solarSystem sun rotate 80 00f 4 1f mercury rotate 150 0f 1 6f venus rotate 215 0f 1 0f earth rotate 20 0f 12 0f moon Nastupnim prikladom vikoristannya F ye komercijnij produkt WebSharper firmi IntelliFactory 2 Ce platforma dlya stvorennya kliyentskih web dodatkiv Vona dozvolyaye pisati kliyentskij kod na F yakij potim bude vidtranslyuvati na JavaScript Taka translyaciya poshiryuyetsya na dostatnyu veliku pidmnozhinu F vklyuchayuchi funkcionalne yadro movi algebrichni tipi danih klasi ob yekti vinyatki j delegati Takozh pidtrimuyetsya znachna chastina standartnoyi biblioteki F vklyuchayuchi robotu z poslidovnostyami sequences podiyami i asinhronnimi obchislyuvalnimi virazami async workflows Vse mozhe buti avtomatichno vidtranslyuvati na cilovu movu JavaScript Krim togo pidtrimuyetsya deyaka chastina standartnih klasiv samogo NET i obsyag pidtrimki bude zrostati Cej produkt primitnij tim sho tut vikoristovuyetsya cilij ryad prijomiv harakternih dlya funkcionalnogo programuvannya Tak v WebSharper vbudovanij DSL dlya zavdannya HTML kodu v yakomu shiroko zastosovuyutsya kombinatori Napriklad nastupnij shmatok kodu na F Div Class Header lt H1 Our Website Br P Hello world Img Src smile jpg bude peretvorenij na vihodi v takij kod HTML lt div class header gt lt h1 gt Our Website lt h1 gt lt br gt lt p gt Hello world lt p gt lt img src smile jpg gt lt div gt Dlya samoyi zh translyaciyi v JavaScript vikoristovuyutsya cituvannya Kod dlya translyaciyi povinen buti pomichenij atributom JavaScriptAttribute uspadkovanim vid standartnogo ReflectedDefinitionAttribute 1 VisnovokVidpovidno do gipotezi lingvistichnoyi vidnosnosti lyudi sho govoryat na riznih movah mislyat i sprijmayut navkolishnyu dijsnist po riznomu Yaksho pripustiti mova programuvannya yaku vikoristovuye programist vplivaye na te yak vin bachit virishennya problemi to ne mozhna ne viznati sho F bude pidshtovhuvati jogo do poshuku prostishih i elegantnishih rishen Bez sumnivu F znajde shiroke zastosuvannya u finansovij sferi ta v galuzi statistiki Krim cogo F zaslugovuye na te shob stati dosit populyarnim u inshih oblastyah hocha b tomu sho robit bagatopotokove programuvannya prostishim i zrozumilishim Slid takozh zaznachiti sho zaraz F ye mabut yedinoyu funkcionalnoyu movoyu programuvannya yaka prosuvayetsya odnim z providnih virobnikiv u galuzi rozrobki programnogo zabezpechennya Vin dozvolyaye vikoristovuvati bezlich vzhe isnuyuchih bibliotek pisati programi dlya riznih platform i sho ne mensh vazhlivo robiti vse ce v suchasnij IDE PrimitkiRelease 16 8 2020 LiteraturaIntelliFactory s WebSharper 16 grudnya 2010 u Wayback Machine Lekciyi Dzhona Harrisona Introduction to Functional Programming Rosijskij pereklad 30 listopada 2010 u Wayback Machine Spisok proektiv sho vikoristovuyut F z vidkritim kodom http stackoverflow com questions 383848 f open source projects 16 chervnya 2010 u Wayback Machine Jon Harrop F for Scientists Wiley Interscience New York NY USA 2008 Paul Hudak The Haskell School of Expression Learning Functional Programming through Multimedia Cambridge University Press 2000 Petricek Accelerator and F nedostupne posilannya z chervnya 2019 Blog Tomasha Petricheka 27 grudnya 2010 u Wayback Machine Tomas Petricek and Jon Skeet Real World Functional Programming with examples in F and C Manning Publications 2009 Cya stattya mistit pravopisni leksichni gramatichni stilistichni abo inshi movni pomilki yaki treba vipraviti Vi mozhete dopomogti vdoskonaliti cyu stattyu pogodivshi yiyi iz chinnimi movnimi standartami lipen 2017 Ce nezavershena stattya pro movi programuvannya Vi mozhete dopomogti proyektu vipravivshi abo dopisavshi yiyi