Тому, скажімо, запит до бази даних чи файлу запису за визначенням не можна було виконати у чистому функціональному стилі. Наприклад, це одна з причин, коли нам потрібні монади.
Нікому не потрібні монади, це лише один із способів описати речі. Насправді це, мабуть, навіть не найкращий спосіб. Деяка форма типізації ефектів , унікальність типів або система, що базується на повній лінійній логіці , теоретично виглядають переконливішими, але все це більш радикальні відступи від відомих систем типу і складніші для вираження. Monadic IO, як знайдено в Haskell, є компромісом між зручністю та простотою, оскільки він, по суті, моделює повністю імперативне програмування таким чином, що легко співіснував із існуючою системою типу ML, яка вже використовується в мові.
Питання - чому ми розглядаємо STDOUT вихід як щось нечисте? Так, будь-який файл-обробник ризикований - ми ніколи не можемо бути впевнені, що дані завжди будуть записуватися. А як щодо STDOUT? Чому ми повинні думати про це як про щось ненадійне? Чи більш надійною є сама оцінка? Я маю на увазі, ми завжди можемо натиснути на курок і, таким чином, перервати обчислення.
Це не так, і ми ні. Введення та вихід із програми в цілому можна просто розглядати як аргументи та результати трактування всієї програми як однієї великої чистої функції. Поки він друкує одне і те ж, що і для stdout, якщо ви живите ним одне і те ж з stdin, це все ще є чистою функцією. Насправді, перед тим, як запровадити монадійний IO, Haskell використовував потокову систему вводу / виводу, яка використовувала чисті ледачі потоки для введення та виведення. Це впало, тому що це було, мабуть, біль, яка може дати вам уявлення про те, чому ви не чули нічого подібного. :]
Щоб зробити сенс дурнішим, розгляньте мінімалістичну езотеричну мову, Lazy K :
Lazy K - зібраний сміттям, референтно прозорий функціональний мову програмування, з простою системою введення-виводу на основі потоку.
Що відрізняє Lazy K від інших таких мов, це майже повна відсутність інших функцій. Наприклад, вона не пропонує інтегровану систему поліморфного типу Hindley-Milner. Він не постачається з великою стандартною бібліотекою з підтримкою незалежного від платформи програмування графічного інтерфейсу та прив’язки до інших мов. Не можна також писати будь-яку подібну бібліотеку, оскільки, між іншим, Lazy K не забезпечує жодного способу визначення або посилання на будь-які функції, крім вбудованих. Ця нездатність доповнюється відповідним відсутністю підтримки чисел, рядків або будь-якого іншого типу даних. Тим не менш, Lazy K - Тюрінг-повний.
(...)
Програми Lazy K живуть у тій же позачасовій платонічній царині, що і математичні функції, яку сторінка Unlambda називає "блаженною цариною чистого нетипового числення лямбда". Так само, як збирання сміття приховує від програміста процес управління пам’яттю, так і референтна прозорість приховує процес оцінювання. Те, що деякий розрахунок необхідний для того, щоб переглянути картину набору Мандельброта, або для того, щоб "запустити" програму Lazy K, є деталізацією реалізації. У цьому суть функціонального програмування.
(...)
Як обробити введення та виведення мовою без побічних ефектів? У певному сенсі введення та вихід не є побічними ефектами; вони є, так би мовити, передніми і зворотними ефектами. Так це в Lazy K, де програма просто трактується як функція від простору можливих входів до простору можливих виходів.
Я сумніваюся, ви знайдете більш функціональну мову, ніж ця!
Майте на увазі, що вищезазначене стосується лише по суті прийняття вводу та виводу чистої функції та підключення їх до stdin / stdout «зовні». Існує велика різниця між цим і наявністю доступу до реальних примітивів вводу / виводу на рівні системи. Деталі про реалізацію читання та запису в потоки можуть витікати домішками, якщо ретельно не зафіксовані.
Я вважаю, що це головна причина того, що ви не можете зробити це безпосередньо в Haskell - розумні випадки використання є тонкими порівняно з використанням монадичного IO, і для останнього є багато користі від доступу до реальної речі. Я вважаю, що тому, наприклад, аргументи командного рядка для програми не передаються просто аргументами main
, хоча інтуїтивно здається, що вони повинні бути.
Ви можете відновити мінімальну версію чого - то подібне в конкретній програмі, хоча - просто захопити аргументи як чисті цінності , а потім використовувати в interact
функцію для іншої частини вашого програми.