Чому добре не покладатися на зміну стану?


16

Це запитання виникає з питань /software/25569/is-haskell-worth-learning

Як правило, робиться кілька часто повторюваних тверджень про те, як Haskell вдосконалює ваші навички кодування іншими мовами, і, тим більше, це тому, що Haskell без громадянства, і це добре.

Чому?

Я бачив, як хтось порівнює це лише з набором лівої руки або, можливо, на день закриває очі і просто покладається на дотик. Невже в цьому є більше?

Це стосується апаратного доступу до пам'яті чи чогось іншого, що є великим збільшенням продуктивності?


2
Haskell є академічним. Я хотів би переглядати лекції Річа Хікі про Clojure - там він викладає вбивчі прагматичні аргументи (подібні до 3-х пунктів Хав'єра, але також зроблені просто).
Робота

2
Так, дивіться clojure.org/state
LennyProgrammers

6
Тільки тому, що Хаскелл "академічний", це не означає, що це непрактично чи не прагматично.
Тихон Єлвіс

Відповіді:


17

є принаймні три великі переваги у верхньої частини моєї голови:

  1. це робить програми більш близькими до математичних виразів. У математиці xце не змінюється, ви просто не знаєте, що це таке, поки ви не вирішите рівняння.

  2. Зрештою, це зміна стану ( в кінці кінців, це як комп'ютер працює на низькому рівні); але мова обмежена певними місцями. що дозволяє компілятору величезних можливостей переміщати код для його оптимізації, оскільки він знає, що він не змінює нічого, від чого залежить інший код.

  3. Паралельний код не потребує синхронізації для доступу до даних, що не змінюються, тому посилюється паралельність, як у системах спільної пам'яті SMP (у всіх багатоядерних системах сьогодні), так і на слабко пов'язаних кластерах.


3
Прихильники функціонального програмування ставлять більшу напругу №3, тобто простіше програмування одночасності.
Mchl

4
@Mchl: В моєму досвіді вони найбільше наголошують на "Легше зрозуміти і міркувати", який відповідає 1. Хоча я вважаю, що це може відрізнятися між мовними спільнотами.
sepp2k

+1, дуже повна відповідь. @ sepp2k: я думаю, обидва важливі. Розум щодо програми - це те, що ми робимо щодня, і це правда, що якщо вам не доведеться перевіряти, чи не змінився стан в якійсь глибоко прихованій функції, набагато простіше читати лише методи високого рівня та фіксувати, що відбувається. Апаратурно-розумний: оскільки ми все більше і більше рухаємось до багатоядерних та багатопроцесорних процесорів (хоча, мабуть, пройде деякий час, перш ніж домашні комп’ютери отримають мультипроцесори), мова, яка сприяє одночасному програмуванню, є премією.
Матьє М.

Хороша відповідь, №2 - це те, що я вважав за відповідь, і хоча я часто читав про переваги багатопроцесорних процесів, це рідко заявляється як чітко, чудова робота.
ocodo

1
@Yttrill, функціональні мови не унікальні тим, що залежать від збирання сміття, а збирання сміття набагато простіше, коли ви маєте справу з незмінними даними. Будь-яке обчислення архітектури, заснованої на інструкціях, означає зміну стану, це не означає, що паралелізувати функціональні мови якось складніше. Функціональні мови гойдаються при паралелізмі; пошук даних паралельно Haskell, це особливість, яку майже неможливо додати до необхідної мови.
dan_waterworth

4

Ось ще одна перевага: зменшена муфта. Якщо у вас є код типу:

 function doStuff(x) { return x + y;}

і в інших місцях:

 function doOtherStuff(x) { y++; return y + x;}

то обидві функції залежать неявно . Немає простого способу сказати, що на дзвінки doStuffвпливає дзвінок doOtherStuff. Не змінюючи стан, вам доведеться зробити з'єднання явним.

Звичайно, це не проблема зі всім змінним станом, а проблема - з широкопроникним змінним станом. Справжнє рішення - мати незмінність за замовчуванням та певний спосіб "маркування" та обмеження змінного стану лише там, де це потрібно.


+1. Багато досвідчених програмістів знають, що не писати код, як описано вище, і це не величезний крок, щоб перейти від "змінного стану погано в цій ситуації" до "давайте серйозно зменшити кількість стану, який ми змінюємо, і запишемо більш функціонально", але це крок що прикро мало хто робить.
dan_waterworth

2

Спрощена відповідь: коли ви бачите ім’я суто функціональною мовою, ви знаєте, що пов’язане значення шляхом простого пошуку його визначення. Якщо у вас є змінні змінні, ви можете лише визначити, яке з декількох призначень було виконано останнім, тому вам доведеться також проаналізувати потік управління, який, в свою чергу, може бути умовним, залишаючи вам кілька можливостей. Для отримання експоненціального вибуху потрібно лише врахувати, що РЗЗ призначень самі залежать від змінних, тому вам доведеться рекурсивно їх аналізувати.

Суть у наведеному вище аналізі полягає в тому, що він неможливий без коментарів, що пояснюють наміри, інваріанти та семантику: це може бути важко інтерпретувати, і може бути важко переконатися, що семантика дотримується у фактичному коді.

Ця відповідь в основному є розширенням точки @ Хав'єра 1.

Я думаю, що це також пояснення популярності шахрайського режиму ОО: з ОО змінено стан інкапсулюється, що робить аналіз набагато простішим, локалізуючи мутації до певної міри, і дозволяє набагато більш міцне вираження і перевірку семантики.

Зауваживши це, функціональне програмування - це не відповідь. Правильна відповідь - це система, яка підтримує як індуктивне (функціональне), так і коіндуктивне (процедурне) програмування, тому правильні інструменти можуть обробляти як бездержавне, так і державне програмування. Просто конструктивна (функціональна) теорія добре встановлена, тоді як теорія управління державою ще знаходиться в зародковому стані.


Змішування функціонального та імперативного програмування - це саме те, що робить Haskell - нормальні функції функціональні, тоді як стаціонарні обчислення можуть бути виражені до-нотацією, яка дозволяє ретельно ізолювати та контролювати стан, що змінюється (серед іншого). Ось чому мовою з найбільш практичною реалізацією STM є Haskell .
Тихон Єлвіс

Як-нотація дійсно не має нічого спільного з станом обчислення як такі . Позначення - це просто простіший синтаксис на вершині монадичних функціональних конвеєрів. Державні обчислення - це лише одна з речей, яку можна виразити за допомогою монад, а отже, і нотації.
Джонатан Стерлінг

Змішане функціональне та імперативне програмування - це те, що робить майже кожна існуюча мова. Haskell, можливо, створив спосіб ізоляції важливих частин, але це не робить його правильним поєднанням: Благодійність більше схожа на те, як має бути (IMHO).
Yttrill

2

Як автор Siege , СУБД, написана в Haskell, деякі можуть назвати мій погляд на стан, що змінюється, конфліктним. Я сподіваюся показати інакше.

Мета стану, що змінюється, - описати поточний стан, у якому знаходиться система. Скажімо, у вас є блог, і він знаходиться за допомогою бази даних, база даних описує публікації, які ви маєте у своєму блозі в той момент, у який ви запитуєте. це. Скільки публікацій існує зараз?

Порівнюйте це з незмінним станом, який використовується для передачі фактів. Скільки повідомлень було 12 серпня?

Факти легко пояснити, стан, що змінюється, ні. Однак стан, що змінюється, - це не якийсь злий нечистий ефект, який слід виганяти з сяг нашого розуму; нам часто потрібно, щоб він існував у світі, що змінюється, у якому ми живемо, нам просто потрібно використовувати його більш щадно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.