{"id":341246,"date":"2022-11-15T03:00:45","date_gmt":"2022-11-15T03:00:45","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=341246"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=341246","title":{"rendered":"<span>\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e cats-effect<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/202\/46b\/a1f\/20246ba1fa0779f8106f3974258c3b14.png\" width=\"780\" height=\"439\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/202\/46b\/a1f\/20246ba1fa0779f8106f3974258c3b14.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u0434\u043e\u043c\u0435\u043d\u0430 \u043f\u0440\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u0430\u043a\u0442\u043e\u0440\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <a href=\"https:\/\/endless4s.github.io\/\"><u>endless4s<\/u><\/a> Scala.<\/p>\n<p>\u041a\u043e\u0434, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443, \u043d\u0435\u0441\u043e\u043c\u043d\u0435\u043d\u043d\u043e, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u044b\u043c \u0446\u0435\u043d\u043d\u044b\u043c \u0430\u043a\u0442\u0438\u0432\u043e\u043c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043a\u043e\u0434\u043e\u043c \u0434\u043e\u043c\u0435\u043d\u0430 \u0441\u0440\u0435\u0434\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u0432 \u043f\u043e \u0434\u043e\u043c\u0435\u043d\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u043e\u043d \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442 \u043e\u043f\u044b\u0442 \u0438 \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0432\u0441\u0435 \u0431\u043e\u0433\u0430\u0442\u0441\u0442\u0432\u043e \u0437\u043d\u0430\u043d\u0438\u0439. \u0425\u043e\u0442\u044f \u0434\u043b\u044f \u0437\u0440\u0435\u043b\u043e\u0441\u0442\u0438 \u0442\u0430\u043a\u0438\u0445 \u0443\u0433\u043b\u0443\u0431\u043b\u0435\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432\u0440\u0435\u043c\u044f, \u0442\u0435\u043d\u0434\u0435\u043d\u0446\u0438\u0438 \u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0431\u044b\u0441\u0442\u0440\u043e \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0438 \u0434\u0430\u0436\u0435 \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u044e\u0442\u0441\u044f \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u043e\u043d\u043d\u044b\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c, \u043a\u0430\u043a \u044d\u0442\u043e <a href=\"https:\/\/www.lightbend.com\/blog\/why-we-are-changing-the-license-for-akka\"><u>\u043d\u0435\u0434\u0430\u0432\u043d\u043e<\/u><\/a> \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0441 Akka. \u0412\u043c\u0435\u0441\u0442\u0435 \u0441 \u0442\u0435\u043c, \u043f\u043e \u043c\u0435\u0440\u0435 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430, \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432, \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u0442\u0435\u0442 \u043f\u043e \u043c\u0435\u0440\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0431\u0430\u0437\u044b. \u042f \u0441\u043b\u044b\u0448\u0430\u043b, \u0447\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u043c \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 COBOL \u0435\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 \u0436\u0438\u0437\u043d\u044c!<\/p>\n<h3>\u0410\u043b\u0433\u0435\u0431\u0440\u044b<\/h3>\n<p>\u0415\u0441\u0442\u044c \u044f\u0437\u044b\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0434\u0435\u0440\u0436\u0430\u043b \u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c: \u044d\u0442\u043e \u044f\u0437\u044b\u043a \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0438, \u0447\u044c\u044f \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0430\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u0430\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u044c\u043d\u0430\u044f \u043d\u043e\u0442\u0430\u0446\u0438\u044f \u043d\u0435 \u0441\u0442\u0430\u0440\u0435\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u0432\u0435\u043a\u043e\u0432. \u0412 \u0438\u0434\u0435\u0430\u043b\u0435, \u044f \u0431\u044b \u0441\u043a\u0430\u0437\u0430\u043b, \u0447\u0442\u043e \u043d\u0430\u0448\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u0442\u0440\u0435\u043c\u0438\u0442\u044c\u0441\u044f \u043a \u0442\u043e\u043c\u0443 \u0436\u0435!<\/p>\n<p>FP (\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435) \u0438 \u0442\u0430\u043a\u0438\u0435 \u0442\u0435\u0445\u043d\u0438\u043a\u0438, \u043a\u0430\u043a tagless-final (\u043d\u0435\u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 [\u043f\u043e\u0434\u0445\u043e\u0434]), \u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f \u043a \u044d\u0442\u043e\u043c\u0443 \u0438\u0434\u0435\u0430\u043b\u0443. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0430\u043b\u0433\u0435\u0431\u0440 \u0438 DSL \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u043c\u0435\u043d\u0430 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u043c \u0438 \u043e\u0442\u0434\u0435\u043b\u0438\u0442\u044c \u0435\u0433\u043e \u043e\u0442 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b. \u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447 \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u0430\u043d\u0430\u043b\u0438\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435. \u042d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0442\u043e\u0447\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435, \u0430 \u043f\u0440\u0438 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 SaaS-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0437\u0430\u0449\u0438\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0434\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u0430.<\/p>\n<h3>\u0410\u043a\u0442\u043e\u0440\u044b<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u0431\u044d\u043a\u0435\u043d\u0434-\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u0435\u043b\u044f\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439: \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0435 CRUD-\u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u0437\u0430 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u043c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0437\u043c \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445; \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0438\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u044c \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430\u043c \u0438 \u0431\u0440\u043e\u043a\u0435\u0440\u0430\u043c, \u0442\u0430\u043a\u0438\u043c \u043a\u0430\u043a Kafka, \u0438 \u0435\u0449\u0435 \u0435\u0441\u0442\u044c \u0430\u043a\u0442\u043e\u0440\u044b. \u042d\u0442\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u0430\u043d\u043d\u0430\u044f \u0438 \u043d\u0435\u0434\u043e\u043e\u0446\u0435\u043d\u0435\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 <a href=\"https:\/\/www.fastcompany.com\/3026758\/inside-erlang-the-rare-programming-language-behind-whatsapps-success\"><u>\u0441\u043f\u043e\u0441\u043e\u0431\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0430 \u0443\u0441\u043f\u0435\u0445\u0443 WhatsApp<\/u><\/a> \u0438 \u0443\u0436\u0435 \u0432 90-\u0445 \u0433\u043e\u0434\u0430\u0445 \u0434\u043e\u0441\u0442\u0438\u0433\u043b\u0430 \u0443\u0440\u043e\u0432\u043d\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u0439 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Erlang_(programming_language)#cite_note-16\"><u>\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0434\u0435\u0432\u044f\u0442\u0438 \u0434\u0435\u0432\u044f\u0442\u043e\u043a<\/u><\/a> \u0432 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u043c\u0443\u0442\u0430\u0442\u043e\u0440\u0430\u0445. \u0410\u043a\u0442\u043e\u0440\u044b \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u0438\u0437 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043c\u0430\u0448\u0438\u043d \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u043a \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f \u0438\u0437 \u043d\u0435\u0435 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438. \u042d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0432 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0435 (\u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043c\u0430\u0448\u0438\u043d\u044b \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f).<\/p>\n<h3>\u041b\u0443\u0447\u0448\u0435\u0435 \u0438\u0437 \u0434\u0432\u0443\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432<\/h3>\n<p>\u0412 Scala Akka, \u0431\u0435\u0437 \u0441\u043e\u043c\u043d\u0435\u043d\u0438\u044f, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0435\u0434\u0443\u0449\u0438\u043c \u0430\u043a\u0442\u043e\u0440\u043d\u044b\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c. \u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0433\u043e API \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438 \u043c\u043e\u043d\u0430\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e: \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0437 OO-\u043a\u043e\u0434\u0430 Java (\u0438 \u0434\u0430\u0436\u0435 \u0434\u043b\u044f .NET, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0443). \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435, \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u044b \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442\u0435 cats-effect \u0438\u043b\u0438 ZIO \u0438 \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0435\u0441\u044c \u043e\u0442 \u0441\u0442\u0435\u043a\u0430 Lightbend, \u0438\u043b\u0438 \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0435\u0441\u044c Akka \u0438 Futures.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u0435\u043c\u0441\u044f \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0432\u0430\u0441 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u044e\u0442 \u0438 \u0430\u043b\u0433\u0435\u0431\u0440\u0430\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043c\u044b\u0448\u043b\u0435\u043d\u0438\u0435, \u0438 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0435\u0439\u0442\u0444\u0443\u043b \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u0442\u043e \u0432\u0430\u043c \u043d\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0431\u043e\u0440: \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043e\u043d\u0438 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432\u043c\u0435\u0441\u0442\u0435! \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0435 \u0440\u0430\u0437\u0443\u043c\u043d\u0443\u044e \u0441\u0442\u0435\u043f\u0435\u043d\u044c \u0437\u0430\u0449\u0438\u0442\u044b \u043e\u0442 \u0431\u0443\u0434\u0443\u0449\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0430\u043a\u0442\u043e\u0440\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0435\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u0442\u0430\u043a\u0430\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c.<\/p>\n<blockquote>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0433\u0440\u0430\u0434\u0438\u0442\u044c \u043a\u043e\u0434 \u0434\u043e\u043c\u0435\u043d\u0430 \u043e\u0442 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0430\u043a\u0442\u043e\u0440\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0435\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u0442\u0430\u043a\u0430\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c<\/p>\n<\/blockquote>\n<h3>\u0427\u0438\u0442\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0430\u0432\u0442\u043e\u0440 (\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044c) \u0441\u043e\u0431\u044b\u0442\u0438\u0439<\/h3>\n<p>\u0428\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0430\u043a\u0442\u043e\u0440 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c\u044e \u2014 \u044d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043e\u0434\u0438\u043d \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0441 \u0434\u043e\u043c\u0435\u043d\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0435\u0439, \u0433\u0434\u0435 \u043e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u0439 \u0441\u0432\u043e\u0435\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u044c\u044e. \u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0430\u043a\u0442\u043e\u0440-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u043d \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0438 \u0444\u043e\u0440\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u043e\u0442\u0432\u0435\u0442. \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c\u044b\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438.<\/p>\n<p>\u041a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f \u043c\u043e\u043d\u0430\u0434 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430: <a href=\"https:\/\/www.scalawithcats.com\/dist\/scala-with-cats.html#sec:monads:reader\"><u>\u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c<\/u><\/a> \u0438 <a href=\"https:\/\/www.scalawithcats.com\/dist\/scala-with-cats.html#writer-monad\"><u>\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044c<\/u><\/a>. \u041a\u0430\u043a \u044d\u0442\u043e <a href=\"https:\/\/www.youtube.com\/watch?v=kDkRRkkVlxQ&amp;ab_channel=ErlangSolutions\"><u>\u0442\u0430\u043a\u0436\u0435<\/u><\/a> \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u043b\u043e\u0441\u044c <a href=\"https:\/\/pavkin.ru\/aecor-part-2\/\"><u>\u0434\u0440\u0443\u0433\u0438\u043c\u0438<\/u><\/a>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u0447\u0442\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u043e\u0442\u0432\u0435\u0442\u0430:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3de\/e27\/b01\/3dee27b01e3fe05b2cc5a4ca6aac10ee.png\" width=\"828\" height=\"137\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3de\/e27\/b01\/3dee27b01e3fe05b2cc5a4ca6aac10ee.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u0433\u043b\u044f\u0434\u043d\u0430\u044f \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043c\u043e\u043d\u0430\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0435\u0439 \u043f\u043e\u0438\u0441\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f-\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044f: <strong>F[ _ ]<\/strong> \u2014 \u044d\u0442\u043e \u0442\u0438\u043f \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0438 \u0441 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u043c \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0433\u043e \u0440\u043e\u0434\u0430, <strong>A<\/strong> \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0442\u0438\u043f \u043a\u043e\u043c\u0430\u043d\u0434\u044b, <strong>write (\u0437\u0430\u043f\u0438\u0441\u044c) <\/strong>\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f, <strong>read (\u0447\u0442\u0435\u043d\u0438\u0435)<\/strong> \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u043c\u0443 \u0441\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u043e \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e, \u0430 <strong>B<\/strong> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b. \u0422\u0438\u043f\u0438\u0447\u043d\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430, \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0431\u0443\u0434\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044d\u0442\u0430\u043f\u044b \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u043c, \u043d\u0435 \u0432\u043e\u043b\u043d\u0443\u0439\u0442\u0435\u0441\u044c: \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0438\u0436\u0435 \u0432\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435, \u0447\u0442\u043e \u0437\u0430 \u044d\u0442\u0438\u043c\u0438 \u043f\u043e\u043d\u044f\u0442\u0438\u044f\u043c\u0438 \u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438.<\/p>\n<h3>\u041f\u0440\u0438\u043c\u0435\u0440: \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0435\u0437\u0434\u043e\u043a<\/h3>\n<p>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0434\u043b\u044f \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0435\u0437\u0434\u043e\u043a. \u0412\u043e\u0442 \u043a\u0430\u043a \u043c\u044b \u0440\u0435\u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0443\u0435\u043c \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435:<\/p>\n<pre><code class=\"scala\">final case class LatLon(lat: Double, lon: Double) final case class Booking(   time: Instant,   passengerCount: Int,   origin: LatLon,   destination: LatLon )<\/code><\/pre>\n<p><em>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043e\u043c\u0435\u043d\u0430 \u0434\u043b\u044f \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0430\u0441\u0441\u0430\u0436\u0438\u0440\u0441\u043a\u0438\u0445 \u043f\u0435\u0440\u0435\u0432\u043e\u0437\u043e\u043a<\/em><\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0430\u043a\u0436\u0435, \u0447\u0442\u043e \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u043d\u0438\u043c \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430. \u0422\u0430\u043a\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0430\u043b\u0433\u0435\u0431\u0440\u044b \u0431\u0435\u0437 \u0442\u0435\u0433\u043e\u0432:<\/p>\n<pre><code class=\"scala\">trait BookingAlg[F[_]] {   def place(booking: Booking): F[AlreadyExists.type \\\/ Unit]   def getBooking: F[Unknown.type \\\/ Booking]      def setRoute(steps: List[LatLon]): F[Unknown.type \\\/ Unit]   def getRoute: F[Unknown.type \\\/ List[LatLon]] } trait BookingRepositoryAlg[F[_]] {   def bookingFor(bookingID: BookingID): BookingAlg[F] } \/\/ note: type \\\/[A, B] = Either[A, B]<\/code><\/pre>\n<p><em>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u0430\u044f \u0430\u043b\u0433\u0435\u0431\u0440\u0430 \u0434\u043b\u044f \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0430: place \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c, getBooking \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0430 setRoute \u0438 getRoute \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0433\u0435\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u0421 \u044d\u0442\u0438\u043c\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f\u043c\u0438 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0435\u0437\u0434\u043a\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043a\u0430\u043a <\/em><code>repository.bookingFor(bookingID).place(booking)<\/code><em>, \u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0438\u0434 <\/em><code>repository.bookingFor(bookingID).setRoute(steps)<\/code><em>.<\/em><\/p>\n<p>\u042d\u0442\u043e\u0442 \u0442\u0440\u0435\u0439\u0442 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0435\u043d \u0432 \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043e\u0431\u0449\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430 \u0438 \u0442.\u0434. \u0412\u0430\u0436\u043d\u044b\u043c \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c \u0437\u0434\u0435\u0441\u044c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e, \u0447\u0442\u043e \u043d\u0430 \u044d\u0442\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u043a\u043e\u0434 \u043d\u0435 \u043e\u043f\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0437\u043d\u0430\u043d\u0438\u044f \u043e\u0431 \u0430\u043a\u0442\u043e\u0440\u0430\u0445, \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445 \u0438 \u0448\u0430\u0440\u0434\u0438\u043d\u0433\u0435. \u041d\u0430\u043f\u0440\u043e\u0442\u0438\u0432, \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442 \u044d\u0442\u0438\u0445 \u043f\u043e\u043d\u044f\u0442\u0438\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435.<\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em>: \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 BookingRepositoryAlg \u0442\u0440\u0435\u0439\u0442\u0443 BookingAlg \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c ID \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0432\u043e \u0432\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b.<\/p>\n<\/blockquote>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0412\u0441\u0435 \u044d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0438 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043d\u043e \u043a\u0430\u043a \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438 \u0433\u0434\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f? \u0418\u043c\u0435\u043d\u043d\u043e \u0437\u0434\u0435\u0441\u044c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c-\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044c.<\/p>\n<p>\u041a\u0430\u043a \u0438 \u0441 Ask \u0438 Tell \u0432 <a href=\"https:\/\/typelevel.org\/cats-mtl\/getting-started.html\"><u>cats MTL<\/u><\/a>, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f-\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044f \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043a\u043b\u0430\u0441\u0441 \u0442\u0438\u043f\u0430 <code>Entity: trait Entity[F[_], S, E] extends StateReader[F, S] with EventWriter[F, E] with Monad[F]<\/code>:<\/p>\n<ul>\n<li>\n<p><code>StateReader<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c read: F[S] (\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u0441\u043c. \u043d\u0438\u0436\u0435).<\/p>\n<\/li>\n<li>\n<p><code>EventWriter<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f: <code>write(events: E*): F[Unit]<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u043e, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u0436\u0430\u0440\u0433\u043e\u043d\u0430:<\/p>\n<pre><code class=\"scala\">final case class BookingEntity[F[_]: Monad: Logger](   entity: Entity[F, BookingState, BookingEvent]) extends BookingAlg[F] {      def place(booking: Booking): F[AlreadyExists.type \\\/ Unit] =      entity.ifUnknownF(entity.write(BookingPlaced(booking)))(_ => AlreadyExists)        def getBooking: F[Unknown.type \\\/ Booking] =      entity.ifKnown(_.definition)(Unknown)      def setRoute(steps: List[LatLon]): F[Unknown.type \\\/ Unit] =      entity.ifKnownF(entity.write(RouteSet(steps))(Unknown)      def getRoute: F[Unknown.type \\\/ List[LatLon]] =      entity.ifKnown(_.route)(Unknown) } \/\/ note: type \\\/[A, B] = Either[A, B]<\/code><\/pre>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (booking entity). <\/em><code>Entity instance<\/code><em> \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 (\u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u044d\u0442\u043e \u043d\u0438\u0436\u0435). write (\u0437\u0430\u043f\u0438\u0441\u044c) \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f. \u043c\u0435\u0442\u043e\u0434\u044b-\u0445\u0435\u043d\u0434\u043b\u0435\u0440\u044b ifKnown, ifUnknown, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 reader (\u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c), \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u044e\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0434\u0438\u0444\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432. \u041b\u044e\u0431\u0430\u044f \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f \u0442\u0430\u043a\u0438\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u0438, \u043f\u0435\u0440\u0435\u043c\u0435\u0436\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0441 \u0447\u0442\u0435\u043d\u0438\u044f\u043c\u0438, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0430 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438: \u0447\u0442\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0441\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0437\u0430 \u043a\u0443\u043b\u0438\u0441\u0430\u043c\u0438.<\/em><\/p>\n<h3>\u0421\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439<\/h3>\n<p>\u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043a \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 (\u0442\u0430\u043a\u0436\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0435 \u043a\u0430\u043a <em>\u0441\u0432\u0435\u0440\u0442\u043a\u0430 <\/em>\u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e) \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u0444\u043e\u0440\u043c\u044b ((<code>Option[S], E) => String \\\/ Option[S]<\/code>). \u041f\u0440\u043e\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u044d\u0442\u043e \u043a\u043e\u0440\u0442\u0435\u0436 \u0438\u0437 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (\u0434\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u043d\u043e \u0435\u0449\u0435 \u043f\u0443\u0441\u0442\u043e\u0435) \u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u043b\u0438\u0431\u043e \u043a \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u043b\u0438\u0431\u043e \u043a \u043e\u0448\u0438\u0431\u043a\u0435. \u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e:<\/p>\n<pre><code class=\"scala\">class BookingEventApplier extends EventApplier[BookingState, BookingEvent] {   def apply(state: Option[BookingState], event: BookingEvent): String \\\/ Option[BookingState] =     (event match {       case BookingPlaced(booking) =>         state           .toLeft(BookingState(definition = booking, route = Nil))           .leftMap(_ => \"Booking already exists\")       case RouteSet(steps: List[LatLon]) =>         state           .toRight(\"Attempt to set route on unknown booking\")           .map(_.copy(route = steps))     }).map(Option(_)) } \/\/ note: type \\\/[A, B] = Either[A, B]<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0432 \u0430\u043b\u0433\u0435\u0431\u0440\u0443, \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438 \u0430\u043f\u043f\u043b\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0434\u043e\u043c\u0435\u043d\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e \u043e\u043d\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043c\u043e\u0434\u0443\u043b\u0435 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0432 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0442\u0440\u043e\u0433\u043e \u043e\u0442\u0434\u0435\u043b\u044f\u0435\u0442 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u0442 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b).<\/p>\n<h3>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>cats.ID<\/code>, \u0438\u043b\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f <code>IO<\/code>, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a\u043e\u0433\u043e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043b\u044f <a href=\"https:\/\/github.com\/typelevel\/munit-cats-effect\"><u>munit<\/u><\/a>:<\/p>\n<pre><code class=\"scala\">class BookingEntitySuite     extends munit.CatsEffectSuite     with munit.ScalaCheckEffectSuite     with Generators {   private val bookingAlg = BookingEntity(EntityT.instance[IO, BookingAlg, BookingEvent])   private implicit val eventApplier: BookingEventApplier = new BookingEventApplier    test(\"place booking\") {     forAllF { booking: Booking =>       bookingAlg         .place(booking)         .run(None)         .map {           case Right((events, _)) =>             assertEquals(               events,               Chain(BookingPlaced(booking))             )           case Left(error) => fail(error)         }     }   } }      <\/code><\/pre>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u044c\u044e\u0442\u0430 munit, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0435\u0433\u043e scalacheck \u0434\u043b\u044f \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u043d\u0430\u0434\u044b-\u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430 EntityT, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0439 endless, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0435 Entity, \u0432 \u0446\u0435\u043b\u0435\u0432\u0443\u044e \u043c\u043e\u043d\u0430\u0434\u0443 (\u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 IO). \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, EntityT \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0435\u044f\u0432\u043d\u043e\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439 eventApplier (\u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0447\u0435\u0440\u0435\u0434\u0443\u044e\u0449\u0438\u0445\u0441\u044f \u0447\u0442\u0435\u043d\u0438\u0439 \u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439).<\/em><\/p>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/h3>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>BookingRepositoryAlg<\/code> \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u0430:<\/p>\n<pre><code class=\"scala\">final case class BookingRepository[F[_]: Monad](     repository: Repository[F, BookingID, BookingAlg])         extends BookingRepositoryAlg[F] {   def bookingFor(bookingID: BookingID): BookingAlg[F] = repository.entityFor(bookingID) }<\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>BookingEntity<\/code>, \u043e\u043f\u0438\u0440\u0430\u044e\u0449\u0435\u0439\u0441\u044f \u043d\u0430 \u043a\u043b\u0430\u0441\u0441 \u0442\u0438\u043f\u0430 <code>Entity<\/code>, \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 <code>Repository<\/code>: \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0445\u044d\u043d\u0434\u043b \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e ID, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u043c \u0435\u043c\u0443 \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f.<\/p>\n<h3>\u041f\u0440\u043e\u0432\u043e\u0434\u043d\u043e\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u00a0<\/h3>\n<p>\u0412\u044b\u0448\u0435 \u043c\u044b \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u0438, \u043a\u0430\u043a \u044d\u0442\u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043e\u0442\u0434\u0435\u043b\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043e\u043c\u0435\u043d\u0430 \u043e\u0442 \u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0435 \u0430\u0441\u043f\u0435\u043a\u0442\u044b &#171;\u043f\u0440\u043e\u0432\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430&#187; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0432\u0443\u0445 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u0442\u0440\u0435\u0439\u0442\u0430 Bookings, \u043e\u0434\u043d\u0430 \u0434\u043b\u044f &#171;\u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439&#187; \u0441\u0442\u043e\u0440\u043e\u043d\u044b (\u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b), \u0434\u0440\u0443\u0433\u0430\u044f \u0434\u043b\u044f &#171;\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439&#187; (\u0430\u043a\u0442\u043e\u0440, \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0449\u0438\u0439 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435).<\/p>\n<p>\u0418\u0437\u044e\u043c\u0438\u043d\u043a\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0438\u043f\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u0430 F \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438 \u043e\u0442\u0432\u0435\u0442\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043a\u043e\u0434\u0438\u0440\u0443\u044e\u0449\u0438\u0445 \u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u044e\u0449\u0438\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432.<\/p>\n<h3>\u0418\u0441\u0445\u043e\u0434\u044f\u0449\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430<\/h3>\n<p>\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0430\u043b\u0433\u0435\u0431\u0440\u044b \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0442\u0438\u043f\u0430 <code>OutgoingCommand[*]<\/code>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0434\u0432\u043e\u0438\u0447\u043d\u0443\u044e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0443 \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0435\u043a\u043e\u0434\u0435\u0440, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u043e\u0442\u0432\u0435\u0442\u0430:<\/p>\n<pre><code class=\"scala\">\/** Represents an outgoing command. Embeds the binary payload and indicates    * the decoder to use for the reply of type `R`.   * @tparam R   *   reply   *\/ trait OutgoingCommand[+R] {   def payload: Array[Byte]   def replyDecoder: Decoder[R] }<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0442\u0438\u043f\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u0430, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0433\u043e \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0435 \u043f\u0440\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 &#171;\u043a\u043b\u0438\u0435\u043d\u0442&#187;<\/p>\n<h3>\u0412\u0445\u043e\u0434\u043d\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430<\/h3>\n<p>\u041d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0435 \u043b\u043e\u0433\u0438\u043a\u0443 \u0438 \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043e\u0442\u0432\u0435\u0442:<\/p>\n<pre><code class=\"scala\">\/** Represents an incoming entity command. Embeds the `Reply` type,    * the ability to run it on the entity algebra in `F` context    * and specifies the encoder to be used to encode the reply.   * @tparam F   *   context   * @tparam Alg   *   entity algebra   *\/ trait IncomingCommand[F[_], Alg[_[_]]] {   type Reply   def runWith(alg: Alg[F]): F[Reply]   def replyEncoder: Encoder[Reply] }<\/code><\/pre>\n<p><em>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0442\u0438\u043f\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u0430, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0433\u043e \u0432\u0445\u043e\u0434\u043d\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0435 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 &#171;\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e&#187; \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430. runWith \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0430\u043a\u0442\u043e\u0440\u0430 \u0438 \u0432\u044b\u0437\u043e\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f.<\/em><\/p>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043d\u0430\u0431\u0436\u0435\u043d\u044b \u043e\u0434\u043d\u0438\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c, \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0449\u0438\u043c <code>trait CommandProtocol[Alg[_[_]]<\/code>. \u0412 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0434\u043a\u043b\u0430\u0441\u0441 <code>ProtobufCommandProtocol<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u0432 protobuf (\u0435\u0441\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0445\u0435\u043b\u043f\u0435\u0440\u044b \u0434\u043b\u044f JSON). \u041f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0438\u0439\u0441\u044f \u043a\u043e\u0434 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043b\u043e\u0442\u043d\u044b\u0439, \u043d\u043e \u043c\u0430\u043b\u043e\u0441\u043b\u043e\u0436\u043d\u044b\u0439; \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043c\u0430\u043f\u043f\u0438\u043d\u0433 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0432 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u0430\u043a \u043a\u043e\u043c\u043c\u0443\u0442\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434:<\/p>\n<pre><code class=\"scala\">class BookingCommandProtocol extends ProtobufCommandProtocol[BookingAlg] {   override def client: BookingAlg[OutgoingCommand[*]] =     new BookingAlg[OutgoingCommand[*]] {       def place(booking: Booking): OutgoingCommand[AlreadyExists.type \\\/ Unit] =         outgoingCommand[proto.BookingCommand, proto.PlaceCommandReply, AlreadyExists.type \\\/ Unit](           command = proto.PlaceBooking(booking.transformInto[proto.Booking]),           replyMapper = _.reply match {             case proto.PlaceCommandReply.AlreadyExistsV1(_) => AlreadyExists.asLeft             case proto.PlaceCommandReply.Unit(_) => ().asRight           }         )       \/\/ ...     }    override def server[F[_]]: Decoder[IncomingCommand[F, BookingAlg]] =     ProtobufDecoder[proto.BookingCommand].map(_.command match {       case proto.PlaceBookingV1(booking) =>         incomingCommand[F, proto.PlaceCommandReply, AlreadyExists.type \\\/ Unit](           run = _.place(booking.transformInto[Booking]),           replyContramapper = {             case Left(AlreadyExists) => proto.PlaceCommandReply.Reply.AlreadyExistsV1()             case Right(()) => proto.PlaceCommandReply.Reply.Unit()           }           )       \/\/ ..     }) } \/\/ note: type \\\/[A, B] = Either[A, B]<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u0434\u043b\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 Booking: \u043a\u043b\u0430\u0441\u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442 <code>CommandProtocol<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043a\u0430\u043a &#171;\u0441\u0435\u0440\u0432\u0435\u0440&#187;, \u0442\u0430\u043a \u0438 &#171;\u043a\u043b\u0438\u0435\u043d\u0442&#187;. \u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>OutgoingCommand<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 protobuf \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u043c\u0430\u043f\u043f\u0435\u0440 \u0434\u043b\u044f \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442\u0430. \u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f protobuf \u0438 \u0432\u044b\u0437\u043e\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 (\u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0432\u044b\u0437\u043e\u0432\u044b transformInto, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/scalalandio.github.io\/chimney\/\"><u>chimney<\/u><\/a> \u0434\u043b\u044f \u043c\u0430\u043f\u043f\u0438\u043d\u0433\u0430 \u0434\u0430\u043d\u043d\u044b\u0445).<\/p>\n<p>\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e, \u0447\u0442\u043e \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u043d\u0435 \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u0434\u043e\u043c\u0435\u043d, \u0437\u0430\u0449\u0438\u0449\u0430\u044f \u0435\u0433\u043e \u043e\u0442 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u0438 \u043c\u0430\u043f\u043f\u0438\u043d\u0433\u0430 \u0431\u043e\u0439\u043b\u0435\u0440\u043f\u043b\u0435\u0439\u0442\u0430. \u0412 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u043c \u0432\u044b\u0448\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u0438\u043c\u0435\u043d\u0430\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 protobuf \u043c\u044b \u0434\u0430\u0436\u0435 \u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u043e \u044f\u0432\u043d\u043e\u043c \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u043e\u043c\u0435\u0440\u0430 \u0432\u0435\u0440\u0441\u0438\u0438.<\/p>\n<h3>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044f\u00bb<\/h3>\n<p>\u041f\u0440\u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0446\u0435\u043b\u0435\u0432\u043e\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0443: <code>OutgoingCommand[*] ~> F<\/code> :<\/p>\n<pre><code class=\"scala\">trait CommandRouter[F[_], ID] {   def routerForID(id: ID): OutgoingCommand[*] ~> F }<\/code><\/pre>\n<p><code>CommandRouter<\/code><em> \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u043c\u0430\u043f\u043f\u0438\u043d\u0433 \u0430\u043b\u0433\u0435\u0431\u0440\u044b \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0439 <\/em><code>CommandProtocol.client<\/code><em>, \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 <\/em><code>OutgoingCommand[*]<\/code><em> \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 F. \u042d\u0442\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 &#171;\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e&#187; \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043a \u0446\u0435\u043b\u0435\u0432\u043e\u043c\u0443 \u0430\u043a\u0442\u043e\u0440\u0443, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0430, \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u043c\u0443 \u0430\u043a\u0442\u043e\u0440\u0443.<\/em><\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 1:<\/em> \u0427\u0442\u043e\u0431\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442\u0430\u043a\u043e\u0439 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0434\u043b\u044f \u0430\u043b\u0433\u0435\u0431\u0440\u044b \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 <a href=\"https:\/\/typelevel.org\/cats-tagless\/typeclasses.html\"><u>FunctorK<\/u><\/a> <a href=\"https:\/\/typelevel.org\/cats-tagless\/\"><u>\u0431\u0435\u0437 \u0442\u0435\u0433\u043e\u0432 cats (cats-tagless)<\/u><\/a>, \u043d\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 <code>\u0434\u0435\u0440\u0438\u0432\u0430\u0446\u0438\u0438 cats-tagless: cats.tagless.derive.functorK[BookingAlg]<\/code>.<\/p>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 2:<\/em> \u043a\u043e\u043c\u0430\u043d\u0434\u0430 router \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438 \u043c\u043e\u043d\u0430\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0439 \u043a \u0430\u043b\u0433\u0435\u0431\u0440\u0435 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f (\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u043c \u043c\u043e\u043d\u0430\u0434 RepositoryT).<\/p>\n<\/blockquote>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/81d\/457\/f7e\/81d457f7ed59768da72728735d89cbad.png\" alt=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 BookingAlg[F].\" title=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 BookingAlg[F].\" width=\"828\" height=\"390\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/81d\/457\/f7e\/81d457f7ed59768da72728735d89cbad.png\"\/><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 BookingAlg[F].<\/figcaption><\/figure>\n<h3>\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0442\u0430\u0439\u043c Akka<\/h3>\n<p>Endless \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u043e\u0434\u0443\u043b\u044c <em>endless-runtime-akka<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 PnP (plug &amp; play) \u0440\u0430\u043d\u0442\u0430\u0439\u043c \u0434\u043b\u044f Akka. \u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0438\u0447\u0442\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u0432\u0430\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u0440\u0430\u043d\u0442\u0430\u0439\u043c.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u0442\u0440\u0435\u0439\u0442\u043e\u0432 \u0434\u0435\u043f\u043b\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430 Akka \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u043e\u0434\u043d\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 <code>deployEntity<\/code>. \u042d\u0442\u043e\u0442 \u0432\u044b\u0437\u043e\u0432 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0432\u0441\u0435 \u0432\u043c\u0435\u0441\u0442\u0435 \u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 cats-\u044d\u0444\u0444\u0435\u043a\u0442 <code>Resource<\/code> \u0441 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u043c \u0447\u0435\u0440\u0435\u0437 Akka Cluster Sharding:<\/p>\n<pre><code class=\"scala\">deployEntity[F, BookingState, BookingEvent, BookingID, BookingAlg, BookingRepositoryAlg](   BookingEntity(_),   BookingRepository(_),   (effector, _) => BookingEffector(effector) ): Resource[F, (BookingRepositoryAlg[F], ActorRef[ShardingEnvelope[Command]])]<\/code><\/pre>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430 deployEntity \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 Booking (\u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u0438\u043f\u0430). \u0412\u044b\u0437\u043e\u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u043d \u0432\u0441\u0435\u043c\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0440\u0435\u0441\u0443\u0440\u0441 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043e\u0440\u0442\u0435\u0436 \u0441 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0432 \u0446\u0435\u043b\u0435\u0432\u0443\u044e \u043c\u043e\u043d\u0430\u0434\u0443, \u0438 \u0441\u0441\u044b\u043b\u043a\u043e\u0439 \u043d\u0430 \u0430\u043a\u0442\u043e\u0440\u0430 \u0440\u0435\u0433\u0438\u043e\u043d\u0430, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0439 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 <\/em><a href=\"https:\/\/doc.akka.io\/docs\/akka\/current\/typed\/cluster-sharding.html#basic-example\"><em><u>ClusterSharding.init<\/u><\/em><\/a><em>, \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f.<\/em><\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 1:<\/em> \u0447\u0442\u043e\u0431\u044b \u0431\u0435\u0437 \u043f\u043e\u0431\u043e\u0447\u043d\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432 \u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u043d\u0435\u044f\u0432\u043d\u0443\u044e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c Akka \u0441 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u043c F, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c \u0434\u043b\u044f \u0430\u043b\u0433\u0435\u0431\u0440, \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440 \u0438 deployEntity \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442 <a href=\"https:\/\/typelevel.org\/cats-effect\/docs\/typeclasses\/async\"><u>Async<\/u><\/a> \u0438\u0437 F. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c <a href=\"https:\/\/typelevel.org\/cats-effect\/docs\/std\/dispatcher\"><u>Dispatcher<\/u><\/a> \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043c\u043e\u043d\u0430\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434 \u0438\u0437 \u043f\u043e\u0442\u043e\u043a\u0430 \u0430\u043a\u0442\u043e\u0440\u0430.<\/p>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 2:<\/em> Ask \u043e\u0442 Akka \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0442\u0440\u0435\u0439\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0433\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0430. \u0412\u043d\u0443\u0442\u0440\u0438 endless \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430 Akka \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e &#171;\u043d\u0435\u0441\u0443\u0449\u0435\u0433\u043e&#187; \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f protobuf, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0446\u0435\u043b\u0438, \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0432 \u0434\u0432\u043e\u0438\u0447\u043d\u043e\u043c \u0432\u0438\u0434\u0435 \u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u0430\u043a\u0442\u043e\u0440\u0430-\u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<\/blockquote>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1ac\/5ab\/cf5\/1ac5abcf5734524eabd01f5cc612e46a.png\" alt=\"\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0430 &quot;\u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439&quot; \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 place(booking) \u0441 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u043e\u043c Akka, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u043e\u0442\u0432\u0435\u0442\u0430.\" title=\"\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0430 &quot;\u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439&quot; \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 place(booking) \u0441 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u043e\u043c Akka, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u043e\u0442\u0432\u0435\u0442\u0430.\" width=\"828\" height=\"552\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1ac\/5ab\/cf5\/1ac5abcf5734524eabd01f5cc612e46a.png\"\/><figcaption>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0430 &#171;\u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439&#187; \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 place(booking) \u0441 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u043e\u043c Akka, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u043e\u0442\u0432\u0435\u0442\u0430.<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/255\/4ea\/5cb\/2554ea5cb670a619bddb41276594e335.png\" alt=\"\u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 &quot;\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439&quot; \u0441\u0442\u043e\u0440\u043e\u043d\u0435, \u043a\u0443\u043b\u044c\u043c\u0438\u043d\u0430\u0446\u0438\u0435\u0439 \u0447\u0435\u0433\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 DSL \u044d\u0444\u0444\u0435\u043a\u0442\u0430 Akka's Cluster Sharding.\" title=\"\u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 &quot;\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439&quot; \u0441\u0442\u043e\u0440\u043e\u043d\u0435, \u043a\u0443\u043b\u044c\u043c\u0438\u043d\u0430\u0446\u0438\u0435\u0439 \u0447\u0435\u0433\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 DSL \u044d\u0444\u0444\u0435\u043a\u0442\u0430 Akka's Cluster Sharding.\" width=\"828\" height=\"572\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/255\/4ea\/5cb\/2554ea5cb670a619bddb41276594e335.png\"\/><figcaption>\u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 &#171;\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439&#187; \u0441\u0442\u043e\u0440\u043e\u043d\u0435, \u043a\u0443\u043b\u044c\u043c\u0438\u043d\u0430\u0446\u0438\u0435\u0439 \u0447\u0435\u0433\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 DSL \u044d\u0444\u0444\u0435\u043a\u0442\u0430 Akka&#8217;s Cluster Sharding.<\/figcaption><\/figure>\n<h3>Effector (\u042d\u0444\u0444\u0435\u043a\u0442\u043e\u0440)<\/h3>\n<p>\u041c\u044b \u0435\u0449\u0435 \u043d\u0435 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u043b\u0438 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u043e\u0431\u043e\u0447\u043d\u044b\u043c\u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0430\u043c\u0438: \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0433\u0438\u0431\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 \u0442\u0438\u043f\u0430 <code>Effector<\/code>: <code>trait Effector[F[_], S] extends StateReader[F, S] with Passivator[F] with Self[F]<\/code>. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u0438\u0437 \u044d\u0442\u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u043e\u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e:<\/p>\n<ul>\n<li>\n<p><code>StateReader<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0447\u0442\u0435\u043d\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><code>Passivator<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0442\u043e\u043d\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u043f\u0430\u0441\u0441\u0438\u0432\u0430\u0446\u0438\u0435\u0439. \u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u044f\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043c\u043e\u0433\u0443\u0442 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u0432 &#171;\u0441\u043f\u044f\u0449\u0438\u0435&#187; \u0444\u043e\u0440\u043c\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f <code>BookingCancelled<\/code>), \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b\u0433\u043e\u0434\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0441\u0441\u0438\u0432\u0430\u0446\u0438\u044e \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u0438\u043b\u0438 \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p><code>Self<\/code> \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0430\u043b\u0433\u0435\u0431\u0440\u0443 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0440\u0430, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0438\u0445 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0438 \u0442\u043e\u0439 \u0436\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c\u044e, \u043e\u0431\u044b\u0447\u043d\u043e \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043a\u0430\u043a <a href=\"https:\/\/www.infoq.com\/news\/2017\/07\/process-managers-event-flows\/\"><u>\u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u044b \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432<\/u><\/a> (\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0441\u043c. <a href=\"https:\/\/endless4s.github.io\/effector.html#self-process-definition\"><u>\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e<\/u><\/a>).<\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em>: \u043c\u043e\u043d\u0430\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0435 <code>Effector<\/code>, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430 \u043c\u043e\u043d\u0430\u0434 <code>EffectorT<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u044b cats-\u044d\u0444\u0444\u0435\u043a\u0442\u0430 \u0432\u043f\u043b\u043e\u0442\u044c \u0434\u043e <code>Async<\/code>, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b, \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0432\u0440\u0435\u043c\u044f, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code>sleep<\/code>, <code>timeoutTo<\/code>.<\/p>\n<\/blockquote>\n<h3>End-less (\u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439)<\/h3>\n<p>\u041c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 <em>\u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e<\/em> \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u044d\u0442\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 <em>\u0442\u0435\u0433<\/em> <em>endless<\/em>, \u0447\u0442\u043e\u0431\u044b \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044c \u043e \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0440\u0430\u0436\u0430\u044e\u0442 \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u044e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (\u043d\u0430\u043c\u0435\u043a \u043d\u0430 <a href=\"https:\/\/okmij.org\/ftp\/tagless-final\/index.html\"><u>tag-less<\/u><\/a>). \u041f\u043e \u043d\u0430\u0448\u0435\u043c\u0443 \u043e\u043f\u044b\u0442\u0443, \u043f\u043e\u0438\u0441\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438 \u0430\u043a\u0442\u043e\u0440\u044b \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043c\u043e\u0449\u043d\u044b\u043c\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0432 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0435. \u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0430\u043b\u0433\u0435\u0431\u0440\u0430\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u0442\u0438\u043b\u044f \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0441 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u0434\u043e\u043c\u0435\u043d\u0430, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0430\u043a\u0442\u043e\u0440\u043e\u0432.<\/p>\n<hr\/>\n<p>\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0430\u0435\u043c \u0432\u0441\u0435\u0445 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0445 \u043d\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u0437\u0430\u043d\u044f\u0442\u0438\u0435 \u043e\u043d\u043b\u0430\u0439-\u043a\u0443\u0440\u0441\u0430 \u00abScala-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u00bb, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 \u043f\u0430\u0440\u0441\u0435\u0440-\u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u043d\u0430 Scala \u0438 \u0431\u0443\u0434\u0435\u043c \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 REST API \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e markdown. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0430 <a href=\"https:\/\/otus.pw\/vAVI\/\">\u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435.<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/otus\/blog\/699294\/\"> https:\/\/habr.com\/ru\/company\/otus\/blog\/699294\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u0434\u043e\u043c\u0435\u043d\u0430 \u043f\u0440\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u0430\u043a\u0442\u043e\u0440\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <a href=\"https:\/\/endless4s.github.io\/\"><u>endless4s<\/u><\/a> Scala.<\/p>\n<p>\u041a\u043e\u0434, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443, \u043d\u0435\u0441\u043e\u043c\u043d\u0435\u043d\u043d\u043e, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u044b\u043c \u0446\u0435\u043d\u043d\u044b\u043c \u0430\u043a\u0442\u0438\u0432\u043e\u043c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043a\u043e\u0434\u043e\u043c \u0434\u043e\u043c\u0435\u043d\u0430 \u0441\u0440\u0435\u0434\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u0432 \u043f\u043e \u0434\u043e\u043c\u0435\u043d\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u043e\u043d \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442 \u043e\u043f\u044b\u0442 \u0438 \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0432\u0441\u0435 \u0431\u043e\u0433\u0430\u0442\u0441\u0442\u0432\u043e \u0437\u043d\u0430\u043d\u0438\u0439. \u0425\u043e\u0442\u044f \u0434\u043b\u044f \u0437\u0440\u0435\u043b\u043e\u0441\u0442\u0438 \u0442\u0430\u043a\u0438\u0445 \u0443\u0433\u043b\u0443\u0431\u043b\u0435\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432\u0440\u0435\u043c\u044f, \u0442\u0435\u043d\u0434\u0435\u043d\u0446\u0438\u0438 \u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0431\u044b\u0441\u0442\u0440\u043e \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0438 \u0434\u0430\u0436\u0435 \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u044e\u0442\u0441\u044f \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u043e\u043d\u043d\u044b\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c, \u043a\u0430\u043a \u044d\u0442\u043e <a href=\"https:\/\/www.lightbend.com\/blog\/why-we-are-changing-the-license-for-akka\"><u>\u043d\u0435\u0434\u0430\u0432\u043d\u043e<\/u><\/a> \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0441 Akka. \u0412\u043c\u0435\u0441\u0442\u0435 \u0441 \u0442\u0435\u043c, \u043f\u043e \u043c\u0435\u0440\u0435 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430, \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432, \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u0442\u0435\u0442 \u043f\u043e \u043c\u0435\u0440\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0431\u0430\u0437\u044b. \u042f \u0441\u043b\u044b\u0448\u0430\u043b, \u0447\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u043c \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 COBOL \u0435\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 \u0436\u0438\u0437\u043d\u044c!<\/p>\n<h3>\u0410\u043b\u0433\u0435\u0431\u0440\u044b<\/h3>\n<p>\u0415\u0441\u0442\u044c \u044f\u0437\u044b\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0434\u0435\u0440\u0436\u0430\u043b \u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c: \u044d\u0442\u043e \u044f\u0437\u044b\u043a \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0438, \u0447\u044c\u044f \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0430\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u0430\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u044c\u043d\u0430\u044f \u043d\u043e\u0442\u0430\u0446\u0438\u044f \u043d\u0435 \u0441\u0442\u0430\u0440\u0435\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u0432\u0435\u043a\u043e\u0432. \u0412 \u0438\u0434\u0435\u0430\u043b\u0435, \u044f \u0431\u044b \u0441\u043a\u0430\u0437\u0430\u043b, \u0447\u0442\u043e \u043d\u0430\u0448\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u0442\u0440\u0435\u043c\u0438\u0442\u044c\u0441\u044f \u043a \u0442\u043e\u043c\u0443 \u0436\u0435!<\/p>\n<p>FP (\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435) \u0438 \u0442\u0430\u043a\u0438\u0435 \u0442\u0435\u0445\u043d\u0438\u043a\u0438, \u043a\u0430\u043a tagless-final (\u043d\u0435\u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 [\u043f\u043e\u0434\u0445\u043e\u0434]), \u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f \u043a \u044d\u0442\u043e\u043c\u0443 \u0438\u0434\u0435\u0430\u043b\u0443. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0430\u043b\u0433\u0435\u0431\u0440 \u0438 DSL \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u043c\u0435\u043d\u0430 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u043c \u0438 \u043e\u0442\u0434\u0435\u043b\u0438\u0442\u044c \u0435\u0433\u043e \u043e\u0442 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b. \u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447 \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u0430\u043d\u0430\u043b\u0438\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435. \u042d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0442\u043e\u0447\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435, \u0430 \u043f\u0440\u0438 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 SaaS-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0437\u0430\u0449\u0438\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0434\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u0430.<\/p>\n<h3>\u0410\u043a\u0442\u043e\u0440\u044b<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u0431\u044d\u043a\u0435\u043d\u0434-\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u0435\u043b\u044f\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439: \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0435 CRUD-\u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u0437\u0430 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u043c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0437\u043c \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445; \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0438\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u044c \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430\u043c \u0438 \u0431\u0440\u043e\u043a\u0435\u0440\u0430\u043c, \u0442\u0430\u043a\u0438\u043c \u043a\u0430\u043a Kafka, \u0438 \u0435\u0449\u0435 \u0435\u0441\u0442\u044c \u0430\u043a\u0442\u043e\u0440\u044b. \u042d\u0442\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u0430\u043d\u043d\u0430\u044f \u0438 \u043d\u0435\u0434\u043e\u043e\u0446\u0435\u043d\u0435\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 <a href=\"https:\/\/www.fastcompany.com\/3026758\/inside-erlang-the-rare-programming-language-behind-whatsapps-success\"><u>\u0441\u043f\u043e\u0441\u043e\u0431\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0430 \u0443\u0441\u043f\u0435\u0445\u0443 WhatsApp<\/u><\/a> \u0438 \u0443\u0436\u0435 \u0432 90-\u0445 \u0433\u043e\u0434\u0430\u0445 \u0434\u043e\u0441\u0442\u0438\u0433\u043b\u0430 \u0443\u0440\u043e\u0432\u043d\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u0439 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Erlang_(programming_language)#cite_note-16\"><u>\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0434\u0435\u0432\u044f\u0442\u0438 \u0434\u0435\u0432\u044f\u0442\u043e\u043a<\/u><\/a> \u0432 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u043c\u0443\u0442\u0430\u0442\u043e\u0440\u0430\u0445. \u0410\u043a\u0442\u043e\u0440\u044b \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u0438\u0437 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043c\u0430\u0448\u0438\u043d \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u043a \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f \u0438\u0437 \u043d\u0435\u0435 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438. \u042d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0432 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0435 (\u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043c\u0430\u0448\u0438\u043d\u044b \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f).<\/p>\n<h3>\u041b\u0443\u0447\u0448\u0435\u0435 \u0438\u0437 \u0434\u0432\u0443\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432<\/h3>\n<p>\u0412 Scala Akka, \u0431\u0435\u0437 \u0441\u043e\u043c\u043d\u0435\u043d\u0438\u044f, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0435\u0434\u0443\u0449\u0438\u043c \u0430\u043a\u0442\u043e\u0440\u043d\u044b\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c. \u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0433\u043e API \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438 \u043c\u043e\u043d\u0430\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e: \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0437 OO-\u043a\u043e\u0434\u0430 Java (\u0438 \u0434\u0430\u0436\u0435 \u0434\u043b\u044f .NET, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0443). \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435, \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u044b \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442\u0435 cats-effect \u0438\u043b\u0438 ZIO \u0438 \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0435\u0441\u044c \u043e\u0442 \u0441\u0442\u0435\u043a\u0430 Lightbend, \u0438\u043b\u0438 \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0435\u0441\u044c Akka \u0438 Futures.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u0435\u043c\u0441\u044f \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0432\u0430\u0441 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u044e\u0442 \u0438 \u0430\u043b\u0433\u0435\u0431\u0440\u0430\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043c\u044b\u0448\u043b\u0435\u043d\u0438\u0435, \u0438 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0435\u0439\u0442\u0444\u0443\u043b \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u0442\u043e \u0432\u0430\u043c \u043d\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0431\u043e\u0440: \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043e\u043d\u0438 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432\u043c\u0435\u0441\u0442\u0435! \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0435 \u0440\u0430\u0437\u0443\u043c\u043d\u0443\u044e \u0441\u0442\u0435\u043f\u0435\u043d\u044c \u0437\u0430\u0449\u0438\u0442\u044b \u043e\u0442 \u0431\u0443\u0434\u0443\u0449\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0430\u043a\u0442\u043e\u0440\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0435\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u0442\u0430\u043a\u0430\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c.<\/p>\n<blockquote>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0433\u0440\u0430\u0434\u0438\u0442\u044c \u043a\u043e\u0434 \u0434\u043e\u043c\u0435\u043d\u0430 \u043e\u0442 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0430\u043a\u0442\u043e\u0440\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0435\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u0442\u0430\u043a\u0430\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c<\/p>\n<\/blockquote>\n<h3>\u0427\u0438\u0442\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0430\u0432\u0442\u043e\u0440 (\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044c) \u0441\u043e\u0431\u044b\u0442\u0438\u0439<\/h3>\n<p>\u0428\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0430\u043a\u0442\u043e\u0440 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c\u044e \u2014 \u044d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043e\u0434\u0438\u043d \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0441 \u0434\u043e\u043c\u0435\u043d\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0435\u0439, \u0433\u0434\u0435 \u043e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u0439 \u0441\u0432\u043e\u0435\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u044c\u044e. \u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0430\u043a\u0442\u043e\u0440-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u043d \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0438 \u0444\u043e\u0440\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u043e\u0442\u0432\u0435\u0442. \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c\u044b\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438.<\/p>\n<p>\u041a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f \u043c\u043e\u043d\u0430\u0434 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430: <a href=\"https:\/\/www.scalawithcats.com\/dist\/scala-with-cats.html#sec:monads:reader\"><u>\u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c<\/u><\/a> \u0438 <a href=\"https:\/\/www.scalawithcats.com\/dist\/scala-with-cats.html#writer-monad\"><u>\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044c<\/u><\/a>. \u041a\u0430\u043a \u044d\u0442\u043e <a href=\"https:\/\/www.youtube.com\/watch?v=kDkRRkkVlxQ&amp;ab_channel=ErlangSolutions\"><u>\u0442\u0430\u043a\u0436\u0435<\/u><\/a> \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u043b\u043e\u0441\u044c <a href=\"https:\/\/pavkin.ru\/aecor-part-2\/\"><u>\u0434\u0440\u0443\u0433\u0438\u043c\u0438<\/u><\/a>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u0447\u0442\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u043e\u0442\u0432\u0435\u0442\u0430:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u0433\u043b\u044f\u0434\u043d\u0430\u044f \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043c\u043e\u043d\u0430\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0435\u0439 \u043f\u043e\u0438\u0441\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f-\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044f: <strong>F[ _ ]<\/strong> \u2014 \u044d\u0442\u043e \u0442\u0438\u043f \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0438 \u0441 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u043c \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0433\u043e \u0440\u043e\u0434\u0430, <strong>A<\/strong> \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0442\u0438\u043f \u043a\u043e\u043c\u0430\u043d\u0434\u044b, <strong>write (\u0437\u0430\u043f\u0438\u0441\u044c) <\/strong>\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f, <strong>read (\u0447\u0442\u0435\u043d\u0438\u0435)<\/strong> \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u043c\u0443 \u0441\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u043e \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e, \u0430 <strong>B<\/strong> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b. \u0422\u0438\u043f\u0438\u0447\u043d\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430, \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0431\u0443\u0434\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044d\u0442\u0430\u043f\u044b \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u043c, \u043d\u0435 \u0432\u043e\u043b\u043d\u0443\u0439\u0442\u0435\u0441\u044c: \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0438\u0436\u0435 \u0432\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435, \u0447\u0442\u043e \u0437\u0430 \u044d\u0442\u0438\u043c\u0438 \u043f\u043e\u043d\u044f\u0442\u0438\u044f\u043c\u0438 \u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438.<\/p>\n<h3>\u041f\u0440\u0438\u043c\u0435\u0440: \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0435\u0437\u0434\u043e\u043a<\/h3>\n<p>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0434\u043b\u044f \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0435\u0437\u0434\u043e\u043a. \u0412\u043e\u0442 \u043a\u0430\u043a \u043c\u044b \u0440\u0435\u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0443\u0435\u043c \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435:<\/p>\n<pre><code class=\"scala\">final case class LatLon(lat: Double, lon: Double) final case class Booking(   time: Instant,   passengerCount: Int,   origin: LatLon,   destination: LatLon )<\/code><\/pre>\n<p><em>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043e\u043c\u0435\u043d\u0430 \u0434\u043b\u044f \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0430\u0441\u0441\u0430\u0436\u0438\u0440\u0441\u043a\u0438\u0445 \u043f\u0435\u0440\u0435\u0432\u043e\u0437\u043e\u043a<\/em><\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0430\u043a\u0436\u0435, \u0447\u0442\u043e \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u043d\u0438\u043c \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430. \u0422\u0430\u043a\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0430\u043b\u0433\u0435\u0431\u0440\u044b \u0431\u0435\u0437 \u0442\u0435\u0433\u043e\u0432:<\/p>\n<pre><code class=\"scala\">trait BookingAlg[F[_]] {   def place(booking: Booking): F[AlreadyExists.type \\\/ Unit]   def getBooking: F[Unknown.type \\\/ Booking]      def setRoute(steps: List[LatLon]): F[Unknown.type \\\/ Unit]   def getRoute: F[Unknown.type \\\/ List[LatLon]] } trait BookingRepositoryAlg[F[_]] {   def bookingFor(bookingID: BookingID): BookingAlg[F] } \/\/ note: type \\\/[A, B] = Either[A, B]<\/code><\/pre>\n<p><em>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u0430\u044f \u0430\u043b\u0433\u0435\u0431\u0440\u0430 \u0434\u043b\u044f \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0430: place \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c, getBooking \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0430 setRoute \u0438 getRoute \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0433\u0435\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u0421 \u044d\u0442\u0438\u043c\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f\u043c\u0438 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0435\u0437\u0434\u043a\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043a\u0430\u043a <\/em><code>repository.bookingFor(bookingID).place(booking)<\/code><em>, \u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0438\u0434 <\/em><code>repository.bookingFor(bookingID).setRoute(steps)<\/code><em>.<\/em><\/p>\n<p>\u042d\u0442\u043e\u0442 \u0442\u0440\u0435\u0439\u0442 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0435\u043d \u0432 \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043e\u0431\u0449\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430 \u0438 \u0442.\u0434. \u0412\u0430\u0436\u043d\u044b\u043c \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c \u0437\u0434\u0435\u0441\u044c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e, \u0447\u0442\u043e \u043d\u0430 \u044d\u0442\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u043a\u043e\u0434 \u043d\u0435 \u043e\u043f\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0437\u043d\u0430\u043d\u0438\u044f \u043e\u0431 \u0430\u043a\u0442\u043e\u0440\u0430\u0445, \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445 \u0438 \u0448\u0430\u0440\u0434\u0438\u043d\u0433\u0435. \u041d\u0430\u043f\u0440\u043e\u0442\u0438\u0432, \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442 \u044d\u0442\u0438\u0445 \u043f\u043e\u043d\u044f\u0442\u0438\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435.<\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em>: \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 BookingRepositoryAlg \u0442\u0440\u0435\u0439\u0442\u0443 BookingAlg \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c ID \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0432\u043e \u0432\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b.<\/p>\n<\/blockquote>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0412\u0441\u0435 \u044d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0438 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043d\u043e \u043a\u0430\u043a \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438 \u0433\u0434\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f? \u0418\u043c\u0435\u043d\u043d\u043e \u0437\u0434\u0435\u0441\u044c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c-\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044c.<\/p>\n<p>\u041a\u0430\u043a \u0438 \u0441 Ask \u0438 Tell \u0432 <a href=\"https:\/\/typelevel.org\/cats-mtl\/getting-started.html\"><u>cats MTL<\/u><\/a>, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f-\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044f \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043a\u043b\u0430\u0441\u0441 \u0442\u0438\u043f\u0430 <code>Entity: trait Entity[F[_], S, E] extends StateReader[F, S] with EventWriter[F, E] with Monad[F]<\/code>:<\/p>\n<ul>\n<li>\n<p><code>StateReader<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c read: F[S] (\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u0441\u043c. \u043d\u0438\u0436\u0435).<\/p>\n<\/li>\n<li>\n<p><code>EventWriter<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f: <code>write(events: E*): F[Unit]<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u043e, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u0436\u0430\u0440\u0433\u043e\u043d\u0430:<\/p>\n<pre><code class=\"scala\">final case class BookingEntity[F[_]: Monad: Logger](   entity: Entity[F, BookingState, BookingEvent]) extends BookingAlg[F] {      def place(booking: Booking): F[AlreadyExists.type \\\/ Unit] =      entity.ifUnknownF(entity.write(BookingPlaced(booking)))(_ => AlreadyExists)        def getBooking: F[Unknown.type \\\/ Booking] =      entity.ifKnown(_.definition)(Unknown)      def setRoute(steps: List[LatLon]): F[Unknown.type \\\/ Unit] =      entity.ifKnownF(entity.write(RouteSet(steps))(Unknown)      def getRoute: F[Unknown.type \\\/ List[LatLon]] =      entity.ifKnown(_.route)(Unknown) } \/\/ note: type \\\/[A, B] = Either[A, B]<\/code><\/pre>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (booking entity). <\/em><code>Entity instance<\/code><em> \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 (\u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u044d\u0442\u043e \u043d\u0438\u0436\u0435). write (\u0437\u0430\u043f\u0438\u0441\u044c) \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f. \u043c\u0435\u0442\u043e\u0434\u044b-\u0445\u0435\u043d\u0434\u043b\u0435\u0440\u044b ifKnown, ifUnknown, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 reader (\u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c), \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u044e\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0434\u0438\u0444\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432. \u041b\u044e\u0431\u0430\u044f \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f \u0442\u0430\u043a\u0438\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u0438, \u043f\u0435\u0440\u0435\u043c\u0435\u0436\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0441 \u0447\u0442\u0435\u043d\u0438\u044f\u043c\u0438, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0430 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438: \u0447\u0442\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0441\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0437\u0430 \u043a\u0443\u043b\u0438\u0441\u0430\u043c\u0438.<\/em><\/p>\n<h3>\u0421\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439<\/h3>\n<p>\u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043a \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 (\u0442\u0430\u043a\u0436\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0435 \u043a\u0430\u043a <em>\u0441\u0432\u0435\u0440\u0442\u043a\u0430 <\/em>\u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e) \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u0444\u043e\u0440\u043c\u044b ((<code>Option[S], E) => String \\\/ Option[S]<\/code>). \u041f\u0440\u043e\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u044d\u0442\u043e \u043a\u043e\u0440\u0442\u0435\u0436 \u0438\u0437 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (\u0434\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u043d\u043e \u0435\u0449\u0435 \u043f\u0443\u0441\u0442\u043e\u0435) \u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u043b\u0438\u0431\u043e \u043a \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u043b\u0438\u0431\u043e \u043a \u043e\u0448\u0438\u0431\u043a\u0435. \u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e:<\/p>\n<pre><code class=\"scala\">class BookingEventApplier extends EventApplier[BookingState, BookingEvent] {   def apply(state: Option[BookingState], event: BookingEvent): String \\\/ Option[BookingState] =     (event match {       case BookingPlaced(booking) =>         state           .toLeft(BookingState(definition = booking, route = Nil))           .leftMap(_ => \"Booking already exists\")       case RouteSet(steps: List[LatLon]) =>         state           .toRight(\"Attempt to set route on unknown booking\")           .map(_.copy(route = steps))     }).map(Option(_)) } \/\/ note: type \\\/[A, B] = Either[A, B]<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0432 \u0430\u043b\u0433\u0435\u0431\u0440\u0443, \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438 \u0430\u043f\u043f\u043b\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0434\u043e\u043c\u0435\u043d\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e \u043e\u043d\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043c\u043e\u0434\u0443\u043b\u0435 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0432 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0442\u0440\u043e\u0433\u043e \u043e\u0442\u0434\u0435\u043b\u044f\u0435\u0442 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u0442 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b).<\/p>\n<h3>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>cats.ID<\/code>, \u0438\u043b\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f <code>IO<\/code>, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a\u043e\u0433\u043e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043b\u044f <a href=\"https:\/\/github.com\/typelevel\/munit-cats-effect\"><u>munit<\/u><\/a>:<\/p>\n<pre><code class=\"scala\">class BookingEntitySuite     extends munit.CatsEffectSuite     with munit.ScalaCheckEffectSuite     with Generators {   private val bookingAlg = BookingEntity(EntityT.instance[IO, BookingAlg, BookingEvent])   private implicit<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-341246","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/341246","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=341246"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/341246\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=341246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=341246"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=341246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}