Повернення вважається шкідливим? Чи може код бути функціональним без нього?


45

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

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

Чиста функція має дві якості:

  1. Виклик його неодноразово на одних і тих же входах завжди дає однаковий результат. Це означає, що воно незмінне. Його стан встановлюється лише один раз.

  2. Він не дає побічних ефектів. Єдина зміна, викликана його викликом, - це результат.

Отже, як можна говорити про те, щоб бути чисто функціональним, якщо ви присягнули використовувати returnяк спосіб спілкування результатів?

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

Я думаю про Tell, не запитуйте як інше ім'я для інкапсуляції. Коли я користуюся, returnто поняття не маю, що мене дзвонило. Я не можу говорити, що це протокол, я повинен змусити його вирішувати мій протокол. Що у багатьох випадках виражається як внутрішній стан. Навіть якщо те, що піддається впливу, не зовсім стан, зазвичай це лише якийсь обчислення, виконане на аргументах стану та введення. Наявність інтерфейсу для реагування дає можливість перетворити результати на щось більш значуще, ніж внутрішній стан чи розрахунки. Це передача повідомлення . Дивіться цей приклад .

Ще в той час, коли на дискових пристроях насправді були диски, а палець - це те, що ви робили в машині, коли колесо було занадто холодне, щоб торкатися пальцями, мене навчали, як дратівливі люди розглядають функції, які мають параметри. void swap(int *first, int *second)здавалося таким зручним, але нас заохочували писати функції, які повертали результати. Тож я взяв це до душі на вірі і почав слідувати за нею.

Але зараз я бачу людей, що будують архітектури, де об’єкти дозволяють, як вони були побудовані, контролюють, куди вони надсилають свої результати. Ось приклад реалізації . Введення об'єкта вихідного порту здається трохи схожим на ідею вихідного параметра. Але саме так об'єкти Tell-Don't-ask розповідають іншим об'єктам, що вони зробили.

Коли я вперше дізнався про побічні ефекти, я подумав про це як вихідний параметр. Нам сказали, щоб не здивувати людей тим, що частина робіт відбулася напрочуд, тобто не дотриманням return resultконвенції. Тепер впевнений, я знаю, що існує купа паралельних проблем з асинхронною ниткою, які побічні ефекти приховують, але повернення насправді є лише умовою, за допомогою якої ви залишаєте результат натиснутим на стек, так що все, що називається, ви можете пізніше пізніше. Це все, що насправді є.

Що я насправді намагаюся запитати:

Є returnєдиний спосіб уникнути всіх цих побічних наслідків і отримати безпеку ниток без замків і т. Д. Або я можу слідувати, сказати, не питати чисто функціонально?


3
Якщо ви вирішите не ігнорувати розділення запитів команд, чи вважаєте ви свою проблему вирішеною?
rwong

30
Подумайте, що опинитися на ударі може бути свідченням того, що ви займаєтесь дизайном, орієнтованим на догми, а не обґрунтуванням плюсів і мінусів кожної конкретної ситуації.
Blrfl

3
Загалом, коли люди говорять про те, що "повернення" є шкідливим, вони говорять, що це проти структурованого програмування, а не функціоналу та єдиного твердження про повернення в кінці процедури (і, можливо, в кінці обох сторін блоку if / else, що сам по собі останній елемент) не входить до цього.
Випадково832

16
@jameslarge: помилкова дихотомія. Не дозволяти собі залучати до дизайну догматичне мислення - це не те саме, що на Дикому Заході / все іде підхід, про який ви говорите. Сенс у тому, щоб не дозволяти догмі перешкоджати доброму, простому, очевидному коду. Загальний закон призначений для лаків; контекст для королів.
Нікол Болас

4
Для мене є одне, що незрозуміло у вашому запитанні: ви кажете, що ви склали присягу, використовуючи "повернення", але, наскільки я можу сказати, ви прямо не пов'язуєте це з іншими своїми поняттями і не кажете, чому ви це зробили. У поєднанні з визначенням чистої функції, що включає результат, ви створюєте щось, що неможливо вирішити.
Даніков

Відповіді:


96

Якщо функція не має ніяких побічних ефектів і нічого не повертає, то ця функція марна. Це так просто.

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

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

Суть полягає у відсутності дурних хитрощів, два принципи вільних функцій від побічних ефектів та "без повернення" просто не сумісні. Крім того, я зазначу, що вони в першу чергу є поганими принципами (насправді догмами), але це інша дискусія.

Такі правила, як "кажи, не питай" або "немає побічних ефектів", не можна застосовувати універсально. Ви завжди повинні враховувати контекст. Програма без побічних ефектів буквально марна. Навіть чисті функціональні мови це визнають. Швидше вони прагнуть відокремити чисті частини коду від побічних ефектів. Суть штату або монад IO в Haskell полягає не в тому, що ви уникаєте побічних ефектів - бо не можете - а в тому, що наявність побічних ефектів явно вказується підписом функції.

Правило Tell-dont-ask застосовується до іншого типу архітектури - стилю, коли об’єкти в програмі є незалежними "акторами", що спілкуються один з одним. Кожен актор в основному автономний і капсульований. Ви можете надіслати йому повідомлення, і він вирішить, як на нього реагувати, але ви не можете вивчити внутрішній стан актора ззовні. Це означає, що ви не можете сказати, чи змінює повідомлення внутрішній стан актора / об'єкта. Стан та побічні ефекти приховані дизайном .


20
@CandiedOrange: чи метод має побічні ефекти прямо чи опосередковано, хоча багато шарів викликів нічого концептуально не змінюють. Це все ж побічний ефект. Але якщо справа в тому, що побічні ефекти трапляються лише через введені об'єкти, щоб ви могли контролювати, які види побічних ефектів можливі, то це звучить як хороша конструкція. Це просто не є побічними ефектами. Це добре OO, але не є чисто функціональним.
ЖакБ

12
@LightnessRacesinOrbit: grep в тихому режимі має код повернення процесу, який буде використовуватися. Якби цього не було, то це було б справді марно
unperson325680

10
@progo: повернення коду не є побічним ефектом; це ефект. Все, що ми називаємо побічним ефектом, називається побічним ефектом, тому що це не зворотний код;)
Легкість Гонки з Монікою

8
@Cubic у цьому справа. Програма без побічних ефектів марна.
Йенс Шодер

5
@mathreadler Це побічний ефект :)
Андрес Ф.

32

Скажіть, не запитуйте, має деякі принципові припущення:

  1. Ви використовуєте об'єкти.
  2. Ваші об’єкти мають стан.
  3. Стан ваших об’єктів впливає на їх поведінку.

Жодне з цих речей не стосується чистих функцій.

Тож давайте розглянемо, чому у нас діє правило "Скажи, не питай". Це правило є попередженням та нагадуванням. Це можна підсумувати так:

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

Інакше кажучи, класи несуть повну відповідальність за підтримання власної держави та дії на ній. Це те, про що йде інкапсуляція.

Від Фаулера :

Tell-Don't-Ask - це принцип, який допомагає людям пам’ятати, що орієнтація на об'єкт полягає в поєднанні даних з функціями, які працюють на цих даних. Це нагадує нам, що замість того, щоб запитувати об’єкт для даних і діяти на цих даних, ми повинні замість цього сказати об’єкту, що робити. Це спонукає нас рухати поведінку до об'єкта, щоб перейти з даними.

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

Порушення TDA

var color = trafficLight.Color;
var elapsed = trafficLight.Elapsed;
If (color == Color.Red && elapsed > 2.Minutes)
    trafficLight.ChangeColor(green);

Не порушення TDA

var result = trafficLight.ChangeColor(Color.Green);

або

var result = await trafficLight.ChangeColorWhenReady(Color.Green);     

В обох останніх прикладах світлофор зберігає контроль над своїм станом та своїми діями.


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

7
Закривання @CandiedOrange є чистими лише у тому випадку, якщо ви не змінюєте прив'язки, що закриваються. В іншому випадку ви втрачаєте референтну прозорість при виклику функції, повернутої після закриття.
Джаред Сміт

1
@JaredSmith і чи не те саме, коли ви говорите про об'єкти? Це не просто проблема незмінності?
candied_orange

1
@bdsl - А тепер ви необачно вказали, куди йдеться про кожне обговорення цього типу із прикладом вашого TrafficLight.refreshDisplay. Якщо ви дотримуєтесь правил, ви приводите до дуже гнучкої системи, яку не розуміє ніхто, окрім оригінального кодера. Я б навіть погодився, що через пару років перерви навіть оригінальний кодер, мабуть, не зрозуміє, що вони також зробили.
Данк

1
"Нерозумно", як в "Не відкривайте інші об'єкти і не дивіться на їхні кишки, а натомість розлийте свої власні кишки (якщо у вас є такі) в інші методи об'єктів; це Шлях" -сильно.
Joker_vD

30

Коли я маю справу з об'єктом, я не запитую його про його внутрішній стан. Я кажу йому, що мені потрібно зробити, і він використовує свій внутрішній стан, щоб зрозуміти, що робити з тим, що я йому сказав.

Ви не тільки запитуєте його внутрішній стан , ви також не запитуєте, чи є у нього взагалі внутрішній стан .

Також скажіть, не питайте! зовсім НЕ означає , не отримує результат у вигляді значення, що повертається ( при умови , за допомогою returnзаяви всередині методу). Це просто означає, що мені байдуже, як ви це робите, але виконайте цю обробку! . І іноді відразу хочеться отримати результат обробки ...


1
Хоча CQS мав би на увазі, що зміна стану та отримання результатів слід розділяти
jk.

7
@jk. Як завжди: як правило, слід розділити зміну стану та повернення результату, але в рідкісних випадках є вагомі причини, щоб поєднати це. Напр .: next()метод ітераторів повинен не лише повернути поточний об'єкт, але й змінити внутрішній стан ітераторів, щоб наступний виклик повернув наступний об’єкт ...
Тимофі Truckle

4
Саме так. Я думаю, що проблема ОП просто пов'язана з нерозумінням / неправильним застосуванням "скажи, не питай". І виправлення цього непорозуміння змушує проблему згасати.
Конрад Рудольф

@KonradRudolph Plus, я не думаю, що це єдине непорозуміння тут. В їх опис "чистої функції" входить "Її стан встановлюється лише один раз". Ще один коментар вказує, що це може означати закриття контексту, але для мене фразові звуки дивно.
Ізката

17

Якщо ви вважаєте returnсебе "шкідливим" (залишатися на своїй фотографії), то замість того, щоб робити функцію на кшталт

ResultType f(InputType inputValue)
{
     // ...
     return result;
}

побудувати його у формі передачі повідомлення:

void f(InputType inputValue, Action<ResultType> g)
{
     // ...
     g(result);
}

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

Якщо це дійсно призводить до «кращих» програм, це дискусійне питання, оскільки воно порушує деякі умовності. Німецький інженер-програміст Ральф Вестфаль створив цілу модель програмування навколо цього, він назвав це "Компоненти, засновані на подіях", за допомогою технології моделювання, яку він називає "Flow Design".

Щоб побачити деякі приклади, почніть з розділу "Переклад на події" цього запису в блозі . Для повного підходу я рекомендую його електронну книгу «Повідомлення як модель програмування - робити OOP так, ніби ти це мав на увазі» .


24
If this really leads to "better" programs is debatableНам залишається лише переглянути код, написаний на JavaScript протягом першого десятиліття цього століття. Jquery та його плагіни були схильні до зворотного виклику парадигми ... зворотного виклику скрізь . У певний момент занадто багато вкладених зворотних дзвінків зробили налагодження кошмаром. Код досі повинні читати люди незалежно від ексцентриситетів програмної інженерії та її "принципів"
Laiv

1
навіть тоді в якийсь момент вам потрібно надати дію, яка виконує побічний ефект або вам потрібен якийсь спосіб повернутися з частини CPS
jk.

12
@Laiv CPS була придумана як оптимізаційна технологія для компіляторів, ніхто фактично не очікував, що програмісти вручну писатимуть код.
Joker_vD

3
@CandiedOrange У слоганській формі "повернення просто говорить продовження, що робити". Справді, створення Схеми було мотивоване спробою зрозуміти модель Актора Хьюітта і дійшов висновку, що актори та закриття - це одне і те ж.
Дерек Елкінс

2
Гіпотетично, звичайно, ви можете записати всю свою заявку у вигляді ряду викликів функцій, які нічого не повертають. Якщо ви не заперечуєте, щоб він був щільно з'єднаний, вам навіть портів не потрібен. Але більшість розумних додатків використовують функції, які повертають речі, тому що ... ну, вони здорові. І як я вважаю, що я адекватно продемонстрував свою відповідь, ви можете returnотримувати дані з функцій і все одно дотримуватися функції Tell Don't Ask, доки ви не командуєте станом об'єкта.
Роберт Харві

7

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

У розподілених системах акторів результат операції зазвичай надсилається як повідомлення назад відправника оригінального запиту. Відправник повідомлення або неявно надається актором виконання, або він (за умовою) явно передається як частина повідомлення. У синхронному передачі повідомлення одна відповідь є подібною до returnтвердження. При асинхронному передачі повідомлень використання повідомлень відповідей є особливо корисним, оскільки дозволяє проводити одночасну обробку в декількох дійових осіб, при цьому все-таки даючи результати.

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


5

Це все питання вражає мене як "порушення рівня".

Ви маєте (принаймні) такі рівні у великому проекті:

  • Системний рівень, наприклад, платформа електронної комерції
  • Рівень підсистеми, наприклад, перевірка користувача: сервер, AD, front-end
  • Індивідуальний програмний рівень, наприклад, один із компонентів вище
  • Рівень актора / модуля [стає мутним залежно від мови]
  • Метод / функціональний рівень.

І так далі, до окремих жетонів.

Насправді не існує необхідності, щоб сутність на рівні методу / функції не поверталася (навіть якщо вона просто повертається this). І немає (у вашому описі) жодної потреби на рівні актора, щоб повернути що-небудь (залежно від мови, яка може бути навіть неможливою). Я думаю, що плутанина полягає в поєднанні цих двох рівнів, і я заперечую, що їх слід чітко міркувати (навіть якщо якийсь даний об'єкт насправді охоплює кілька рівнів).


2

Ви згадуєте, що ви хочете відповідати як принципу OOP "говорити, не питати", так і функціональному принципу чистих функцій, але я не зовсім бачу, як це призвело до того, щоб ти ухилився від заяви.

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

Одним із прикладів такого підходу є вбудований Python tupleта frozensetтипи даних. Ось типове використання замороженого набору:

small_digits = frozenset([0, 1, 2, 3, 4])
big_digits = frozenset([5, 6, 7, 8, 9])
all_digits = small_digits.union(big_digits)

print("small:", small_digits)
print("big:", big_digits)
print("all:", all_digits)

Який надрукує наступне, демонструючи, що метод об'єднання створює новий заморожений набір із власним станом, не впливаючи на старі об'єкти:

малий: заморожений набір ({0, 1, 2, 3, 4})

великий: заморожений набір ({5, 6, 7, 8, 9})

всі: заморожений набір ({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})

Інший обширний приклад подібних незмінних структур даних - бібліотека Immutable.js Facebook у Immutable.js . В обох випадках ви починаєте з цих будівельних блоків і можете створювати об’єкти домену вищого рівня, які дотримуються одних і тих же принципів, досягаючи функціонального підходу OOP, який допомагає легше інкапсулювати дані та міркувати про них. І незмінність також дозволяє отримати користь від можливості поділитися такими об'єктами між потоками, не турбуючись про замки.


1

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

Я намагаюся зрівняти деякі переваги, більш конкретно, імперативного та функціонального програмування (природно, не отримуючи всіх переваг, але намагаюся отримати левову частку обох), хоча returnце насправді принципово для цього в для мене прямо в моді в багатьох випадках.

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

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

Вузлопровід

введіть тут опис зображення

І ця схема є приблизно настільки, наскільки я намагався замалювати це (і, хоча це було просто, мені довелося продовжувати його змінювати і переосмислювати). Одразу я схиляюсь до думки, що дизайн із таким рівнем розв'язки та абстрагування виявить, що в кодовій формі стає дуже важко міркувати, тому що оркестрові організації, які передають усі ці речі для складного світу, можуть бути дуже важкими слідкуйте за всіма цими взаємодіями та запитами, щоб створити потрібний конвеєр. У візуальній формі, однак, може бути досить просто просто намалювати ці речі як графік і зв’язати все, а також побачити, що відбувається в інтерактивному режимі.

Щодо побічних ефектів, я можу бачити, що це не містить "побічних ефектів" в тому сенсі, що ці запити можуть на стеку виклику призводити до ланцюжка команд для виконання кожного потоку, наприклад (я не рахую цього як "побічний ефект" в прагматичному сенсі, оскільки він не змінює жодного стану, що має відношення до зовнішнього світу, поки такі команди фактично не виконуються - практична мета в більшості програмного забезпечення - не усунути побічні ефекти, а відкласти їх і централізувати) . Крім того, виконання команд може створити новий світ на відміну від мутації існуючого. Мій мозок справді оподатковується просто намагаючись осягнути все це, однак відсутність спроби прототипувати ці ідеї. Я також не робив

Як це працює

Тож для уточнення я уявляв, як ви насправді це програмуєте. Те, як я бачив це, було насправді діаграмою вище, що фіксувала робочий процес програміста для користувача. Ви можете перетягнути світлофор у світ, перетягнути таймер, надати йому минулий період (після "його побудови"). У таймері є On Intervalподія (вихідний порт), ви можете підключити його до світлофора, щоб у таких подіях він повідомляв світлу кружляти по своїх кольорах.

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

І вони повністю інкапсулюють свій стан і нічого про це не розкривають (якщо ці "події" не вважаються ТМІ, і тоді мені доведеться багато що переосмислити), вони говорять один одному, що потрібно робити побічно, вони не просять. І вони убер відірвані. Нічого нічого не знає, крім цієї узагальненої абстракції портів вводу / виводу.

Випадки практичного використання?

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

Сигнали та слоти

Ця конструкція мені виглядала дивно знайомою, поки я не зрозумів, що це в основному сигнали та слоти, якщо ми не будемо брати до уваги нюанси того, як вона реалізована. Основне питання для мене полягає в тому, наскільки ефективно ми можемо запрограмувати ці окремі вузли (об’єкти) на графіку, як суворо дотримуватися функцію Tell, Don't Ask, прийняту до ступеня уникнення returnвисловлювань, і чи можемо ми оцінити цей графік без мутацій (у паралельна, наприклад, відсутність блокування). Ось де магічні переваги полягають не в тому, як ми поєднуємо ці речі разом, а в тому, як вони можуть бути реалізовані в цій мірі інкапсуляції відсутніх мутацій. І те і інше здається мені здійсненним, але я не впевнений, наскільки це було б широко застосовано, і саме тут я трохи затуманився, намагаючись розібратися з можливими випадками використання.


0

Я чітко бачу тут протікання впевненості. Здається, що «побічний ефект» - це добре відомий і загальновизнаний термін, але насправді це не так. Залежно від ваших визначень (яких насправді немає в ОП), побічні ефекти можуть бути абсолютно необхідними (як @JacquesB вдалося пояснити) або нещадно неприйняті. Або, зробивши один крок до роз'яснення, необхідно розрізнити бажані побічні ефекти, яких не любить приховувати (в цьому моменті з'являється відомий ІО Хаскелла: це не що інше, як спосіб бути явним) і небажані побічні ефекти як результат помилок коду та подібних речей . Це досить різні проблеми і тому потребують різних міркувань.

Отже, я пропоную почати з перефразування себе: "Як ми визначаємо побічний ефект і що дане визначення (і) говорять про його взаємозв'язок із твердженням" return "?".


1
"в цьому моменті з'являється відомий ІО Хаскелла: це не що інше, як спосіб бути явним" - явність, безумовно, є користю монадичного IO Haskell, але є ще один момент: він забезпечує засіб виділення побічного ефекту, щоб бути цілком поза мовою - хоча звичайні реалізації насправді цього не роблять, в основному, це стосується ефективності, концептуально це правда: монада IO може вважатися способом повернення інструкції до деякого середовища, яке повністю знаходиться поза межами Програма Haskell разом із посиланням на функцію, яку слід продовжувати після її завершення.
Жуль
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.