Чи слід побудувати об’єкти стану, що моделюються, з типом ефекту?
Якщо ви вже використовуєте систему ефектів, вона, швидше за все, має a Ref
тип безпечного інкапсуляції змінного стану.
Тому я кажу: моделюйте стаціонарні об’єкти сRef
. Оскільки створення (а також доступ до них) вже є ефектом, це автоматично зробить і створення послуги ефективною.
Це акуратно простежує ваше оригінальне запитання.
Якщо ви хочете вручну керувати внутрішнім зміненим станом регулярно, var
вам належить переконатися в тому, що всі операції, що торкаються цього стану, вважаються ефектами (і, швидше за все, також робляться безпечними для потоків), що є виснажливим і схильним до помилок. Це можна зробити, і я погоджуюсь з відповіддю @ atl, що вам не потрібно чітко робити створення об'єкта, що створює стан, ефективно (доки ви зможете жити зі втратою референтної цілісності), але чому б не врятувати себе від неприємностей і обійняти інструменти вашої системи ефектів до кінця?
Я думаю, що все це є чистим і детермінованим. Просто не відносно прозорі, оскільки отриманий екземпляр кожен раз відрізняється. Це вдалий час для використання ефекту типу?
Якщо ваше запитання можна перефразувати як
Чи є додаткові переваги (крім правильно працюючої реалізації з використанням "слабшого типу класу") референтної прозорості та локальних міркувань достатньо, щоб виправдати використання типу ефекту (який вже повинен використовуватися для доступу до держави та мутації) також для держави створення?
потім: Так, абсолютно .
Щоб навести приклад, чому це корисно:
Наведене нижче чудово працює, навіть якщо створення послуги не дало ефекту:
val service = makeService(name)
for {
_ <- service.doX()
_ <- service.doY()
} yield Ack.Done
Але якщо ви перефактуєте це, як показано нижче, ви не отримаєте помилку під час компіляції, але ви змінили поведінку і, швидше за все, ввели помилку. Якби ви заявилиmakeService
ефективність, рефакторинг не перевірить тип і не буде відхилений компілятором.
for {
_ <- makeService(name).doX()
_ <- makeService(name).doY()
} yield Ack.Done
Отримавши назву методу як makeService
(і з параметром теж), слід чітко зрозуміти, що робить метод, і що рефакторинг не був безпечним ділом, але "локальне міркування" означає, що вам не потрібно шукати під час іменування конвенцій та втілення цього поняття makeService
: Будь-який вираз, який не можна механічно перетасувати навколо (дедупілювати, зробити ледачим, зробити нетерплячим, мертвий код усунутий, паралельний, затримати, кешований, очищений з кешу тощо), не змінюючи поведінки ( тобто не є "чистим") слід набрати як ефективний.
delay
і повернути F [послугу] . Як приклад, див.start
Метод на IO , він повертає IO [Fiber [IO,?]] Замість простого волокна.