{"id":333774,"date":"2022-05-28T21:00:23","date_gmt":"2022-05-28T21:00:23","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=333774"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=333774","title":{"rendered":"<span>\u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u043e\u0439 \u0441\u0432\u0451\u0440\u0442\u043a\u0438 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0435\u0440\u0435\u0432\u044c\u0435\u0432<\/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<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\u00a0\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u043e\u0439 \u0441\u0432\u0451\u0440\u0442\u043a\u0438. \u0414\u0430\u043b\u0435\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0443\u0436\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u00a0\u0441 \u0442\u0438\u043f\u043e\u043c <code>Fix<\/code> &#8212; \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0442\u043e\u0440\u043e\u0432, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c <a href=\"#main\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0438<\/a>.<\/p>\n<h3>\u041f\u0440\u0430\u0432\u0430\u044f \u0441\u0432\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u0441\u043f\u0438\u0441\u043a\u043e\u0432<\/h3>\n<p>\u0421\u0432\u0451\u0440\u0442\u043a\u0430 \u2014 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0442\u0438\u043f\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0434\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0447\u0438\u0441\u0435\u043b \u0432 \u0438\u0445 \u0441\u0443\u043c\u043c\u0443, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0441\u0430\u043c\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u043a\u0430\u043a \u0431\u044b \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u0442\u0441\u044f. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c\u00a0\u043f\u0440\u0430\u0432\u0443\u044e \u0441\u0432\u0451\u0440\u0442\u043a\u0443 \u0434\u043b\u044f \u0441\u043f\u0438\u0441\u043a\u0430:<\/p>\n<pre><code class=\"haskell\">foldr :: (a -> b -> b) -> b -> [a] -> b foldr f ini (x:xs) = f x (foldr f ini xs) foldr _ ini _      = ini<\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>f<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u00a0\u0441\u043f\u0438\u0441\u043a\u0430, \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432 \u043d\u0435\u0439 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u043e\u0431\u0445\u043e\u0434 \u0441\u043f\u0438\u0441\u043a\u0430. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432 <code>foldr<\/code>\u00a0\u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0445\u043e\u0434 \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u0432\u044b\u0437\u043e\u0432 \u043d\u0430\u0448\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0435\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u043d\u0430\u043c \u0436\u0435 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u00a0\u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443. \u0412\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u2014 \u043c\u043e\u0436\u0435\u043c \u043b\u0438 \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0443\u044e <code>foldr<\/code>,\u00a0 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u041e\u0442\u0432\u0435\u0442 \u2014 \u0434\u0430, \u043c\u043e\u0436\u0435\u043c. \u041a\u0430\u043a, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u00a0\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u0445.<\/p>\n<h3>\u0422\u0438\u043f Fix<\/h3>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043f\u0438\u0441\u043e\u043a \u0438 \u0432\u044b\u0434\u0435\u043b\u0438\u043c \u043d\u0430 \u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0431\u0449\u0438\u0439 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0445\u00a0\u0442\u0438\u043f\u043e\u0432 \u043f\u0430\u0442\u0442\u0435\u0440\u043d.<\/p>\n<pre><code class=\"haskell\">data List a = Nil | Elem a (List a)<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0443\u0431\u0440\u0430\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438\u0437 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u0438\u043f\u0430:<\/p>\n<pre><code class=\"haskell\">data List a b = Nil | Elem a b<\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u0434\u0432\u0443\u043c\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438:<\/p>\n<pre><code class=\"haskell\">xs = Elem 1 (Elem 2 Nil)<\/code><\/pre>\n<p>\u041f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e! \u0423 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u2014 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u043b\u0438\u0448\u0435\u043d\u043e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438. \u041d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u043d\u043e \u043d\u043e \u2014 <code>xs<\/code> \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f \u043d\u0435 <code>List Int<\/code>, \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0436\u0434\u0435, \u0430 <code>List Int (List Int (List Int a))<\/code>. \u0422\u043e \u0435\u0441\u0442\u044c\u00a0\u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c, \u0438\u043c\u0435\u044e\u0449\u0438\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440. \u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u00a0\u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0442\u0438\u043f \u0441 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439.<\/p>\n<pre><code class=\"haskell\">newtype Fix f = Fix { unFix :: f (Fix f) }<\/code><\/pre>\n<p>\u0420\u0430\u043d\u044c\u0448\u0435 \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>b<\/code> \u0432 \u0442\u0438\u043f\u0435 <code>List<\/code> \u043c\u044b \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u043b\u0438 <code>List a<\/code>, \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u043b\u0438 \u043c\u044b\u00a0\u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>List a<\/code> \u0432 <code>Fix<\/code>, \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 <code>Fix<\/code> \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0437\u0430 \u043d\u0430\u0441:<\/p>\n<pre><code class=\"haskell\">type FixedList a = Fix (List a)<\/code><\/pre>\n<p>\u0421\u043d\u043e\u0432\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u0434\u0432\u0443\u043c\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438:<\/p>\n<pre><code class=\"haskell\">xs :: FixedList Int xs = Fix (Elem 1 (Fix (Elem 2 (Fix Nil))))<\/code><\/pre>\n<p>\u041c\u043e\u0436\u043d\u043e \u0440\u0430\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u2014 \u043c\u044b \u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438\u0437 \u0442\u0438\u043f\u0430 \u0443\u0431\u0440\u0430\u043b\u0438 \u0438 \u0442\u0438\u043f \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432 \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432\u00a0\u0432 \u0441\u043f\u0438\u0441\u043a\u0435. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043a \u043b\u044e\u0431\u043e\u043c\u0443 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u043c\u0443 \u0442\u0438\u043f\u0443, \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0432\u00a0\u0435\u0433\u043e \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043d\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u0438\u043f\u0430.<\/p>\n<h4>\u041f\u0438\u0448\u0435\u043c \u0441\u0432\u0451\u0440\u0442\u043a\u0443 \u0434\u043b\u044f Fix<\/h4>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u0438\u043f\u0430 <code>List<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0432\u0435\u043b\u0438, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f, \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043a\u043b\u0435\u0439\u043a\u0438 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u0432\u0441\u0435\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0441\u043f\u0438\u0441\u043a\u0430 \u0441 \u0434\u0432\u0443\u043c\u044f\u00a0\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438. \u0414\u0430\u043b\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u043a\u043e\u0434 \u043d\u0430 \u043f\u0441\u0435\u0432\u0434\u043e\u0445\u0430\u0441\u043a\u0435\u043b\u0435, \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u00a0\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0441\u043f\u0438\u0441\u043a\u0430:<\/p>\n<pre><code class=\"haskell\">xs :: FixedList Int xs = Fix (Elem 1 (Fix (Elem 2 (Fix Nil))))<\/code><\/pre>\n<p><strong>\u041f\u0435\u0440\u0432\u044b\u0439 \u0448\u0430\u0433<\/strong><\/p>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c <code>Nil<\/code> \u0432 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443:<\/p>\n<pre><code class=\"haskell\">f :: List Int String -> String f Nil = \"\"<\/code><\/pre>\n<p><strong>\u0412\u0442\u043e\u0440\u043e\u0439 \u0448\u0430\u0433<\/strong><\/p>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0432 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430:<\/p>\n<pre><code class=\"haskell\">f :: List Int String -> String f (Elem 2 acc) = \"2\" ++ acc<\/code><\/pre>\n<p><strong>\u0422\u0440\u0435\u0442\u0438\u0439 \u0448\u0430\u0433<\/strong><\/p>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0432 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430:<\/p>\n<pre><code class=\"haskell\">f :: List Int String -> String f (Elem 1 acc) = \"1\" + acc<\/code><\/pre>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c &#171;12&#187;. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 <code>f<\/code> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043f\u0438\u0441\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c\u00a0\u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u043d\u0430\u0448\u0443 \u0441\u0432\u0451\u0440\u0442\u043a\u0443.<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0438\u0434\u0435\u044f \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0434\u043e\u043b\u0436\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0432\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u0442\u0438\u043f\u0430 <code>Fix<\/code> \u043f\u043e\u043d\u044f\u0442\u043d\u0430, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0435\u0451.<\/p>\n<pre><code class=\"haskell\">foldFix :: Functor f => (f a -> a) -> Fix f -> a foldFix f = f . fmap (foldFix f) . unFix<\/code><\/pre>\n<p>\u0422\u0438\u043f \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0444\u0443\u043d\u043a\u0442\u043e\u0440\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u043e\u043d\u0438\u043a\u0430\u0442\u044c \u0432 \u0435\u0433\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u0432\u0451\u0440\u0442\u043a\u0443, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043a\u043e\u043d\u0446\u0430.\u00a0<code>a<\/code> \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0438\u043f\u043e\u043c \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0442\u0435\u0445 \u043c\u0435\u0441\u0442\u0430\u0445, \u043a\u0443\u0434\u0430 \u043c\u044b \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u0438\u043f\u0430 \u0434\u043b\u044f \u0438\u0437\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438.<\/p>\n<h4>\u041f\u0438\u0448\u0435\u043c \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u043a\u0443 \u0434\u043b\u044f Fix<\/h4>\n<p>\u041f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u0442\u0438\u043f\u0430 <code>Fix<\/code>. \u0420\u0430\u0437\u0432\u0451\u0440\u0442\u043a\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442\u00a0\u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e:<\/p>\n<pre><code class=\"haskell\">unfoldFix :: Functor f => (a -> f a) -> a -> Fix f unfoldFix f = Fix . fmap (unfoldFix f) . f<\/code><\/pre>\n<h3>\u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c:<\/h3>\n<pre><code class=\"haskell\">{-# LANGUAGE DeriveFunctor #-}  module Main (main) where  import Prelude hiding (showList)  newtype Fix f = Fix { unFix :: f (Fix f) }  foldFix :: Functor f => (f a -> a) -> Fix f -> a foldFix f = f . fmap (foldFix f) . unFix  unfoldFix :: Functor f => (a -> f a) -> a -> Fix f unfoldFix f = Fix . fmap (unfoldFix f) . f  type List a = Fix (ListF a)  data ListF a b = Nil | Elem a b deriving Functor  showList :: Show a => List a -> String showList = foldFix showListF  showListF :: Show a => ListF a String -> String showListF Nil          = \"\" showListF (Elem x acc) = show x ++ acc  -- \u0421\u043f\u0438\u0441\u043e\u043a \u0447\u0438\u0441\u0435\u043b \u043e\u0442 0 \u0434\u043e 3 list :: List Int list = unfoldFix (\\x -> if x &lt;= 3 then Elem x (x + 1) else Nil) 0  -- \u0412\u044b\u0432\u0435\u0434\u0435\u0442 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c 0123 main :: IO () main = putStrLn $ showList list<\/code><\/pre>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439 \u0442\u0438\u043f <code>Fix<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0443\u0436\u0435\u00a0\u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432 \u043f\u0430\u043a\u0435\u0442\u0435 <a href=\"https:\/\/hackage.haskell.org\/package\/data-fix\" rel=\"noopener noreferrer nofollow\">data-fix<\/a>.<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440<\/h3>\n<p><a class=\"anchor\" name=\"main\" id=\"main\"><\/a><\/p>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u044e\u0431\u043e\u0433\u043e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u00a0\u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>foldFix<\/code> \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u044d\u0442\u043e\u043c \u0442\u0438\u043f\u0435 \u0432 \u043e\u0434\u043d\u043e. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043b\u044e\u0441\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e\u00a0\u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430 (\u0434\u0430\u043b\u0435\u0435 \u0410\u0421\u0414):<\/p>\n<ol>\n<li>\n<p> \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430 \u0431\u0435\u0437 \u044f\u0432\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442\u00a0\u043e\u0448\u0438\u0431\u043e\u043a, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u043c\u044b \u0437\u0430\u0431\u044b\u043b\u0438 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u043b\u0438\u0441\u0442\u043e\u0432 \u0434\u0435\u0440\u0435\u0432\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0 \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0432\u044b\u0437\u0432\u0430\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0435 <code>If<\/code> \u0434\u043b\u044f \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0438 <code>then<\/code> \u0431\u043b\u043e\u043a\u0430, \u0430 \u0434\u043b\u044f <code>else<\/code> \u0437\u0430\u0431\u044b\u043b\u0438. \u0422\u0430\u043a\u0436\u0435 \u044d\u0442\u043e\u00a0\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u0435\u043d\u0435\u0435 \u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434, \u0442\u0430\u043a \u043a\u0430\u043a \u044f\u0432\u043d\u043e\u0439 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438 \u0432 \u043a\u043e\u0434\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p> \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043d\u0430\u0431\u0434\u0438\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u043b\u0438\u0441\u0442 \u0434\u0435\u0440\u0435\u0432\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u0438 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0451 \u043d\u0430\u043b\u0438\u0447\u0438\u0435.\u00a0 \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u043b\u0438\u0441\u0442 \u0434\u0435\u0440\u0435\u0432\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043d\u0430\u0431\u0436\u0451\u043d \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0430\u0439\u043b\u0430 \u0441 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043e\u0439, \u0447\u0442\u043e\u00a0 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u043e\u0439, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430.<\/p>\n<h4>\u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441<\/h4>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441 \u0442\u0438\u043f\u043e\u043c int \u0438 bool, \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 if, \u0446\u0438\u043a\u043b while \u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0435\u00a0\u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u043d\u0438\u0436\u0435:<\/p>\n<pre><code>def fac_rec(x) {     if x == 2 {         return x     } else {         return x * fac_rec(x - 1)     } }  def fac_iter(x) {     res = 1     while x >= 2 {         res = x * res         x = x - 1     }     return res }  def main() {     while true {         print(\"Enter mode:\\n1) recursive\\n2) iterative\\n3) exit\\n\")         mode = read()         if mode == 1 || mode == 2 {             print(\"Enter x: \")             x = read()             res = 0             if mode == 1 {                 res = fac_rec(x)             } else {                 res = fac_iter(x)             }             print(\"x!: \", res, \"\\n\")         } else {             if mode == 3 {                 break             } else {                 print(\"mode is invalid\\n\")             }         }     } }<\/code><\/pre>\n<h4>\u0410\u0421\u0414<\/h4>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u0442\u0438\u043f \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0410\u0421\u0414:<\/p>\n<pre><code class=\"haskell\">data Function = Function     { funName :: Text     , funArgs :: [Text]     , funBody :: Expr     } deriving Eq  data Expr     = IntLit Int     | BoolLit Bool     | Var Text     | UnOp UnOp Expr     | BinOp BinOp Expr Expr     | Assign Text Expr     | If Expr Expr (Maybe Expr)     | While Expr Expr     | Seq [Expr]     | Call Text [Expr]     | Break     | Read     | Print [PrintArg]     | Return (Maybe Expr)     deriving Eq  data UnOp = Neg | Not deriving Eq  data BinOp     = Add | Sub | Mul | Div     | Lt | Le | Gt | Ge     | Eq | Ne | And | Or     deriving Eq  data PrintArg     = StrArg Text     | ExprArg Expr     deriving Eq<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u0443\u0431\u0435\u0440\u0451\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432:<\/p>\n<pre><code class=\"haskell\">module Lang.Ast.Types where  data Function b = Function     { funName :: Text     , funArgs :: [Text]     , funBody :: b     } deriving (Eq, Functor, Foldable, Traversable)  type Expr = Fix ExprF  data ExprF a     = IntLit Int     | BoolLit Bool     | Var Text     | UnOp UnOp a     | BinOp BinOp a a     | Assign Text a     | If a a (Maybe a)     | While a a     | Seq [a]     | Call Text [a]     | Break     | Read     | Print [PrintArg a]     | Return (Maybe a)     deriving (Functor, Foldable, Traversable)  data UnOp = Neg | Not deriving Eq  data BinOp     = Add | Sub | Mul | Div     | Lt | Le | Gt | Ge     | Eq | Ne | And | Or     deriving Eq  data PrintArg a     = StrArg Text     | ExprArg a     deriving (Functor, Foldable, Traversable)<\/code><\/pre>\n<h4>\u0421\u043d\u0430\u0431\u0436\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u043b\u0438\u0441\u0442 \u0410\u0421\u0414 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439 \u0432 \u0444\u0430\u0439\u043b\u0435<\/h4>\n<pre><code class=\"haskell\">module Lang.Ast.Annotated where  -- \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0441\u043d\u0430\u0431\u0436\u0451\u043d\u043d\u043e\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439 type PosExpr = Fix PosExprF  type PosExprF = AnnF SourceSpan ExprF  -- \u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0442\u043e\u0440\u0430 f \u0441 \u0444\u0443\u043d\u043a\u0442\u043e\u0440\u043e\u043c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 type AnnF ann f = Compose (Ann ann) f  -- \u0424\u0443\u043d\u043a\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u0435\u0433\u043e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e data Ann ann a = Ann     { annotation :: ann     , annotated  :: a     } deriving (Functor, Foldable, Traversable)  -- \u041d\u0430\u0447\u0430\u043b\u043e \u0438 \u043a\u043e\u043d\u0435\u0446 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 data SourceSpan = SourceSpan     { spanBegin :: SourcePos     , spanEnd   :: SourcePos     } deriving (Eq, Show)  instance Semigroup SourceSpan where   s1 &lt;> s2 = SourceSpan ((min on spanBegin) s1 s2) ((max on spanEnd) s1 s2)  -- \u041f\u043e\u0437\u0438\u0446\u0438\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 data SourcePos = SourcePos     { posFile   :: FilePath     , posLine   :: Int     , posColumn :: Int     } deriving (Eq, Show)  instance Ord SourcePos where     compare (SourcePos _ b1 e1) (SourcePos _ b2 e2) =  compare b1 b2                                                     &lt;> compare e1 e2  -- \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0438\u0437 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430 stripAnnotation :: Functor f => Fix (AnnF ann f) -> Fix f stripAnnotation = unfoldFix (annotated . getCompose . unFix)<\/code><\/pre>\n<h4>\u0418\u043d\u0441\u0442\u0430\u043d\u0441 Eq<\/h4>\n<p>\u041d\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u0438\u043f\u0430 <code>Fix f<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u043b\u0430\u0441\u0441\u0430 <code>Eq<\/code>, \u0435\u0441\u043b\u0438\u00a0\u0434\u043b\u044f <code>f<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u043b\u0430\u0441\u0441\u0430 <code>Eq1<\/code>. \u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f <code>Eq1<\/code> \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432 <code>ExprF<\/code>, <code>PrintArg<\/code> \u0438 <code>Ann<\/code>.<\/p>\n<pre><code class=\"haskell\">import Data.Functor.Classes (Eq1(..))  instance Eq1 ExprF where     liftEq f a b = case (a, b) of     (IntLit i1, IntLit i2)                 -> i1 == i2     (BoolLit b1, BoolLit b2)               -> b1 == b2     (Var v1, Var v2)                       -> v1 == v2     (UnOp op1 e1, UnOp op2 e2)             -> op1 == op2                                            &amp;&amp; f e1 e2     (BinOp op1 e11 e12, BinOp op2 e21 e22) -> op1 == op2                                            &amp;&amp; f e11 e21                                            &amp;&amp; f e12 e22     (Assign v1 e1, Assign v2 e2)           -> v1 == v2 &amp;&amp; f e1 e2     (If cnd1 th1 el1, If cnd2 th2 el2)     -> f cnd1 cnd2                                            &amp;&amp; f th1 th2     &amp;&amp; liftEq f el1 el2     (While cnd1 body1, While cnd2 body2)   -> f cnd1 cnd2 &amp;&amp; f body1 body2     (Seq ss1, Seq ss2)                     -> liftEq f ss1 ss2     (Call fn1 args1, Call fn2 args2)       -> fn1 == fn2                                            &amp;&amp; liftEq f args1 args2     (Break, Break)                         -> True     (Read, Read)                           -> True     (Print args1, Print args2)             -> liftEq (liftEq f) args1 args2     (Return v1, Return v2)                 -> liftEq f v1 v2     _                                      -> False  instance Eq1 PrintArg where     liftEq f a b = case (a, b) of     (StrArg s1, StrArg s2)   -> s1 == s2     (ExprArg e1, ExprArg e2) -> f e1 e2     _                        -> False  instance Eq ann => Eq1 (Ann ann) where     liftEq f (Ann a1 g1) (Ann a2 g2) = a1 == a2 &amp;&amp; f g1 g2<\/code><\/pre>\n<h4>\u041f\u0430\u0440\u0441\u0435\u0440<\/h4>\n<p>\u041f\u0440\u043e \u0430\u043f\u043f\u043b\u0438\u043a\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u044b \u0435\u0441\u0442\u044c \u043a\u0443\u0447\u0430 \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0441\u0442\u0430\u0442\u0435\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u043e\u043b\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0430\u0440\u0441\u0435\u0440\u0430, \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/ci.cyberfined.xyz\/cyberfined\/fix-lang\/src\/commit\/b42a973fd9ea71353bc368883aecd848bc8714a3\/src\/Lang\/Parser.hs\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>. \u0417\u0434\u0435\u0441\u044c \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0441\u043d\u0430\u0431\u0436\u0430\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439 \u0432 \u0444\u0430\u0439\u043b\u0435, \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043a\u043e\u0434 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u0434\u043b\u044f \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442:<\/p>\n<pre><code class=\"haskell\">import Data.Fix               (Fix(..)) import Data.Functor.Compose   (Compose(..)) import Data.Text              (Text) import Data.Void              (Void) import Text.Megaparsec hiding (SourcePos(..))  import Lang.Ast.Annotated import Lang.Ast.Types  import qualified Text.Megaparsec as Megaparsec import qualified Text.Megaparsec.Char.Lexer as Lexer  type Parser = Parsec Void Text  pIntLit :: Parser PosExpr pIntLit = annotate (IntLit &lt;$> Lexer.decimal)  annotate :: Parser (f (Fix (AnnF SourceSpan f)))          -> Parser (Fix (AnnF SourceSpan f)) annotate p = do     from &lt;- convertPos &lt;> getSourcePos     let ann = SourceSpan from to     pure $ Fix (Compose $ Ann ann res)     where convertPos :: Megaparsec.SourcePos -> SourcePos           convertPos (Megaparsec.SourcePos path from to) =             SourcePos path (Megaparsec.unPos from) (Megaparsec.unPos to)<\/code><\/pre>\n<h4>\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440<\/h4>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043c\u043e\u043d\u0430\u0434\u044b, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b. \u0412 \u043e\u0434\u043d\u0443 \u043c\u043e\u043d\u0430\u0434\u0443 \u0431\u0443\u0434\u0443\u0442\u00a0\u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0441\u043d\u0430\u0431\u0436\u0451\u043d\u043d\u044b\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439, \u0430 \u0432 \u0434\u0440\u0443\u0433\u0443\u044e \u2014 \u043d\u0435 \u0441\u043d\u0430\u0431\u0436\u0451\u043d\u043d\u044b\u0435. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b\u00a0\u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432\u044b\u0432\u043e\u0434\u0430 \u043e\u0448\u0438\u0431\u043e\u043a. \u0412 \u043e\u0434\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439,\u00a0\u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u2014 \u043d\u0435\u0442:<\/p>\n<pre><code class=\"haskell\">-- \u0412 \u044d\u0442\u0443 \u043c\u043e\u043d\u0430\u0434\u0443 \u0431\u0443\u0434\u0443\u0442 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0441\u043d\u0430\u0431\u0436\u0451\u043d\u043d\u044b\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439 newtype PosInterpreterM a = PosInterpreterM     { runPosInterpreterM :: ReaderT (Context PosInterpreterM) IO a     } deriving ( Functor                , Applicative                , Monad                , MonadReader (Context PosInterpreterM)                , MonadIO                )  -- \u0412 \u044d\u0442\u0443 \u043c\u043e\u043d\u0430\u0434\u0443 \u0431\u0443\u0434\u0443\u0442 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043d\u0435 \u0441\u043d\u0430\u0431\u0436\u0451\u043d\u043d\u044b\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439 newtype InterpreterM a = InterpreterM     { runInterpreterM :: ReaderT (Context InterpreterM) IO a     } deriving ( Functor                , Applicative                , Monad                , MonadReader (Context InterpreterM)                , MonadIO                )  data Context m = Context     { ctxVariables   :: IORef (HashMap Text Value) -- \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438     , ctxFunctions   :: HashMap Text (FuncInfo m)  -- \u0424\u0443\u043d\u043a\u0446\u0438\u0438     , ctxSourceSpan  :: SourceSpan                 -- \u041f\u043e\u0437\u0438\u0446\u0438\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f     , ctxSourceCode  :: Text                       -- \u041a\u043e\u0434 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b     , ctxIsBreak     :: IORef Bool                 -- \u041d\u0443\u0436\u043d\u043e \u043b\u0438 \u0432\u044b\u0439\u0442\u0438 \u0438\u0437 \u0446\u0438\u043a\u043b\u0430     , ctxIsReturn    :: IORef Bool                 -- \u041d\u0443\u0436\u043d\u043e \u043b\u0438 \u0432\u044b\u0439\u0442\u0438 \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438     , ctxReturnValue :: IORef (Maybe Value)        -- \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0435\u0440\u043d\u0443\u043b\u0430 \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f     }  data FuncInfo m = FuncInfo     { infArgs :: ![Text]            -- \u0421\u043f\u0438\u0441\u043e\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438     , infBody :: !(m (Maybe Value)) -- \u0422\u0435\u043b\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438     }  data Value     = IntValue Int     | BoolValue Bool     deriving Eq<\/code><\/pre>\n<p>\u041d\u0430\u043c \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 \u0442\u0438\u043f\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0438:<\/p>\n<pre><code class=\"haskell\">class Monad m => MonadError m where     throwError :: Text -> m a<\/code><\/pre>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u044b \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u043c\u043e\u043d\u0430\u0434:<\/p>\n<pre><code class=\"haskell\">instance MonadError PosInterpreterM where     throwError err = do         SourcePos fpath ln cl &lt;- asks (spanBegin . ctxSourceSpan)         src &lt;- asks ctxSourceCode         let strLn = Text.pack $ show ln             margin = Text.replicate (Text.length strLn + 2) \" \"             errMsg =  Text.pack fpath &lt;> \":\" &lt;> strLn &lt;> \":\"                                       &lt;> Text.pack (show cl)                                       &lt;> \": error:\\n\" &lt;> err &lt;> \"\\n\"             line = Text.takeWhile (\/='\\n')                  . (!!(ln-1))                  . iterate (Text.tail . Text.dropWhile (\/= '\\n')) $ src             prettyLine =  margin &lt;> \"|\\n \" &lt;> strLn &lt;> \" | \" &lt;> line &lt;> \"\\n\"                        &lt;> margin &lt;> \"|\\n\"         liftIO $ throwIO $ InterpreterException (errMsg &lt;> prettyLine)  instance MonadError InterpreterM where throwError = liftIO . throwIO . InterpreterException  data InterpreterException = InterpreterException Text  instance Show InterpreterException where show (InterpreterException err) =  \"InterpreterException: \"                                     ++ Text.unpack err  instance Exception InterpreterException where<\/code><\/pre>\n<p>\u0414\u043b\u044f <code>PosInterpreterM<\/code> \u043e\u0448\u0438\u0431\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>InterpreterException: example.lang:19:12:    | 19 |     while 1 {    | 1 is not a boolean value<\/code><\/pre>\n<p>\u0410 \u0434\u043b\u044f <code>InterpreterM<\/code> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c:<\/p>\n<pre><code>InterpreterException: 1 is not a boolean value<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0431\u0435\u0437 \u043f\u043e\u0437\u0438\u0446\u0438\u0438. \u041a\u0430\u0436\u0434\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043b\u0438\u0431\u043e\u00a0<code>Int<\/code>, \u043b\u0438\u0431\u043e <code>Bool<\/code>, \u043b\u0438\u0431\u043e \u043d\u0438\u0447\u0435\u0433\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>m (Maybe Value)<\/code>:<\/p>\n<pre><code class=\"haskell\">interpretExpr :: (MonadReader (Context m) m, MonadError m, MonadInput m)               => Expr               -> m (Maybe Value) interpretExpr = foldFix interpretExprF  -- \u041f\u043e\u043a\u0430 \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0443 interpretExprF :: (MonadReader (Context m) m, MonadError m, MonadInput m)                => ExprF (m (Maybe Value))                -> m (Maybe Value) interpretExprF = undefined<\/code><\/pre>\n<p>\u0421\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u0435\u0439\u0447\u0430\u0441 \u2014 \u043c\u044b \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0441 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f\u00a0\u0442\u0443 \u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>interpretExprF<\/code>, \u0447\u0442\u043e \u0438 \u0434\u043b\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0431\u0435\u0437 \u043f\u043e\u0437\u0438\u0446\u0438\u0438. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u0437\u043e\u0432\u043e\u043c\u00a0<code>interpretExprF<\/code> \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043b\u0438\u0441\u0442\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043a\u043b\u0430\u0441\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043f\u043e\u0437\u0438\u0446\u0438\u044e\u00a0\u044d\u0442\u043e\u0433\u043e \u043b\u0438\u0441\u0442\u0430 \u0432 \u043a\u043e\u0434\u0435 \u0438 \u0437\u0430\u0442\u0435\u043c \u0443\u0431\u0438\u0440\u0430\u0442\u044c \u0435\u0451 \u0438\u0437 \u043b\u0438\u0441\u0442\u0430. \u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u00a0\u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u044f\u0432\u043d\u043e \u043a\u043b\u0430\u0441\u0442\u044c \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u043b\u0438\u0441\u0442\u00a0\u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0432 \u043a\u043e\u0434\u0435:<\/p>\n<pre><code class=\"haskell\">-- \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0435\u0440\u0435\u0432\u0430, \u044f\u0432\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u043f\u043e\u0437\u0438\u0446\u0438\u044e interpretExpr (IntLit x pos) = ...  -- \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0435\u0440\u0435\u0432\u0430, \u043d\u0435\u044f\u0432\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u043f\u043e\u0437\u0438\u0446\u0438\u044e interpretExprF (IntLit x) = ...<\/code><\/pre>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f:<\/p>\n<pre><code class=\"haskell\">adi :: Functor f => (f a -> a) -> ((Fix f -> a) -> Fix f -> a) -> Fix f -> a adi f g = g (f . fmap (adi f g) . unFix)<\/code><\/pre>\n<p>\u042f \u043f\u043e\u0437\u0430\u0438\u043c\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0435\u0451 \u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <a href=\"https:\/\/github.com\/haskell-nix\/hnix\/blob\/9c7a0461f7982a72506c373c26a5195036488cb6\/src\/Nix\/Utils.hs#L345\" rel=\"noopener noreferrer nofollow\">hnix<\/a>.\u00a0\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0438\u0434\u0435\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435\u043c \u0441\u0432\u0451\u0440\u0442\u043a\u0438 \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>g<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f\u00a0\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u043b\u0438\u0441\u0442\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u0438\u0437 \u043b\u0438\u0441\u0442\u0430\u00a0\u043f\u043e\u0437\u0438\u0446\u0438\u044e, \u043a\u043b\u0430\u0441\u0442\u044c \u0435\u0451 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0441\u0432\u0451\u0440\u0442\u043a\u0438. \u0414\u0435\u043b\u0430\u0442\u044c \u043c\u044b \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u043c\u00a0\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>setContext<\/code>:<\/p>\n<pre><code class=\"haskell\">setContext :: (PosExpr -> InterpeterM (Maybe Value))            -> PosExpr            -> InterpeterM (Maybe Value) setContext f expr = local (\\ctx -> ctx { ctxSourceSpan = sourceSpan }) $     f expr   where sourceSpan = annotation $ getCompose $ unFix expr<\/code><\/pre>\n<p>\u0421\u043e\u0431\u0435\u0440\u0451\u043c \u0432\u0441\u0451 \u0432\u043c\u0435\u0441\u0442\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0441\u043d\u0430\u0431\u0436\u0451\u043d\u043d\u044b\u0445 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439:<\/p>\n<pre><code class=\"haskell\">interpretPosExpr :: PosExpr -> PosInterpreterM (Maybe Value) interpretPosExpr = adi (interpretExprF . annotated . getCompose) setContext<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>interpretExprF<\/code>. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>shouldSkip<\/code>,\u00a0\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 <code>ctxIsBreak<\/code> \u0438\u00a0<code>ctxIsReturn<\/code> \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u043f\u043e\u0441\u043b\u0435 <code>Break<\/code> \u0438 <code>Return<\/code> \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u043b\u0438\u0441\u044c:<\/p>\n<pre><code class=\"haskell\">shouldSkip :: (MonadReader (Context m) m, MonadIO m)            => m (Maybe a)            -> m (Maybe a) shouldSkip ma = do     brk &lt;- asks ctxIsBreak >>= liftIO . readIORef     ret &lt;- asks ctxIsReturn >>= liftIO . readIORef     if brk || ret then pure Nothing else ma<\/code><\/pre>\n<p>\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 \u043d\u0430\u0447\u043d\u0451\u043c \u0441 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445 \u0438 \u0431\u0443\u043b\u0435\u0432\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439. \u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0438\u0445 \u0432\u00a0\u0442\u0438\u043f <code>Value<\/code> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u043e\u0432 <code>IntValue<\/code> \u0438 <code>BoolValue<\/code> \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e:<\/p>\n<pre><code class=\"haskell\">interpretExprF :: (MonadReader (Context m) m, MonadError m, MonadIO m)                => ExprF (m (Maybe Value))                -> m (Maybe Value) interpretExprF = shouldSkip . \\case     IntLit i  -> pure $ Just $ IntValue i     BoolLit b -> pure $ Just $ BoolValue b<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c. \u0415\u0441\u043b\u0438 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432 \u0445\u044d\u0448-\u0442\u0430\u0431\u043b\u0438\u0446\u0435\u00a0<code>ctxVariables<\/code>, \u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0435\u0433\u043e, \u0438\u043d\u0430\u0447\u0435 \u043a\u0438\u0434\u0430\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"haskell\">    Var x ->         variablesRef &lt;- asks ctxVariables         mValue &lt;- HashMap.lookup v &lt;$> liftIO (readIORef variablesRef)         case mValue of             Nothing    -> throwError $ \"undefined variable \" &lt;> v             Just value -> pure $ Just value<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u043d\u0430\u0440\u043d\u044b\u0435 \u0438 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0442\u0440\u0438 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"haskell\">-- \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 Int, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0438\u0437 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f, -- \u0438\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0443 intValue :: MonadError m => m (Maybe Value) -> m Int intValue mVal = mVal >>= \\case     Just (IntValue val) -> pure val     Just BoolValue{}    -> typeError \"int\" \"bool\"     Nothing             -> typeError \"int\" \"unit\"  -- \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 Bool, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0438\u0437 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f, -- \u0438\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0443 boolValue :: MonadError m => m (Maybe Value) -> m Bool boolValue mVal = mVal >>= \\case     Just (BoolValue val) -> pure val     Just IntValue{}      -> typeError \"bool\" \"int\"     Nothing              -> typeError \"bool\" \"unit\"  -- \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438 typeError :: MonadError m => Text -> Text -> m a typeError expected actual = throwError $  \"type error: expected \"                                        &lt;> expected                                        &lt;> \" actual \"                                        &lt;> actual<\/code><\/pre>\n<p>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0441\u0430\u043c\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c. \u042f \u043f\u0440\u0438\u0432\u0451\u043b \u043a\u043e\u0434 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0440\u0451\u0445 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435\u00a0\u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u043e\u0445\u043e\u0436\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0438 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"haskell\">    UnOp op mVal -> case op of         Neg -> Just . IntValue . negate &lt;$> intValue mVal         Not -> Just . BoolValue . not &lt;$> boolValue mVal     BinOp op mVal1 mVal2 -> case op of         Add -> Just . IntValue &lt;$> ((+) &lt;$> intValue mVal1 &lt;*> intValue mVal2)         Eq  -> Just . BoolValue &lt;$> ((==) &lt;$> mVal1 &lt;*> mVal2)         And -> do             val1 &lt;- boolValue mVal1             if val1                then Just . BoolValue &lt;$> boolValue mVal2                else pure $ Just $ BoolValue False<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u043e \u0441\u043f\u0438\u0441\u043a\u0443 \u0438\u0434\u0451\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u044f. \u0414\u043b\u044f \u043d\u0435\u0451 \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0449\u0451 \u043e\u0434\u043d\u0443 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/p>\n<pre><code class=\"haskell\">anyValue :: MonadError m => m (Maybe a) -> m a anyValue mVal = mVal >>= maybe (typeError \"int or bool\" \"unit\") pure<\/code><\/pre>\n<p>\u041a\u043e\u0434 \u0434\u043b\u044f \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u043d\u0438\u0436\u0435:<\/p>\n<pre><code class=\"haskell\">    Assign var mVal -> do         val &lt;- anyValue mVal         variablesRef &lt;- asks ctxVariables         liftIO $ modifyIORef variablesRef (HashMap.insert var val)         pure Nothing<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"haskell\">    If mCnd th el -> do         cnd &lt;- boolValue mCnd         if cnd then th else fromMaybe (pure Nothing) el<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 <code>Break<\/code> \u0438 <code>Return<\/code>:<\/p>\n<pre><code class=\"haskell\">   -- \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c ctxIsBreak     Break -> do         brkRef &lt;- asks ctxIsBreak         liftIO $ writeIORef brkRef True         pure Nothing      -- \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c ctxIsReturn, \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435     -- \u0438 \u043a\u043b\u0430\u0434\u0451\u043c \u0435\u0433\u043e \u0432 ctxReturnValue     Return mVal -> do         val &lt;- fromMaybe (pure Nothing) mVal         returnValue &lt;- asks ctxReturnValue         isReturn &lt;- asks ctxIsReturn         liftIO $ do             writeIORef returnValue val             writeIORef isReturn True             pure Nothing<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0446\u0438\u043a\u043b\u0430 while \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"haskell\">-- \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0442\u0435\u043b\u043e \u0446\u0438\u043a\u043b\u0430, \u043f\u043e\u043a\u0430 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u043d\u0435 \u0432\u0435\u0440\u043d\u0451\u0442 False while :: Monad m => m Bool -> m a -> m () while mCond mbody = do     cond &lt;- mCond     when cond (mbody >> while mCond mbody)  -- \u0415\u0441\u043b\u0438 \u0432 \u0446\u0438\u043a\u043b\u0435 \u0431\u044b\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u043e\u0434\u043d\u0430 \u0438\u0437 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 break \u0438\u043b\u0438 return, -- \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u043e\u0434\u043d\u0430 \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 ctxIsBreak \u0438\u043b\u0438 ctxIsReturn. -- \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u044d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435. -- \u0415\u0441\u043b\u0438 \u043e\u0434\u043d\u0430 \u0438\u0437 \u043d\u0438\u0445 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c False, \u0438\u043d\u0430\u0447\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c -- \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u044f. \u041f\u0435\u0440\u0435\u0434 \u0432\u044b\u0445\u043e\u0434\u043e\u043c \u0438\u0437 \u0446\u0438\u043a\u043b\u0430, \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c ctxIsBreak. whileCond :: (MonadReader (Context m) m, MonadError m, MonadIO m)           => m (Maybe Value)           -> m Bool whileCond mCond = do     brkRef &lt;- asks ctxIsBreak     brk &lt;- liftIO $ readIORef brkRef     ret &lt;- asks ctxIsReturn >>= liftIO . readIORef     if brk || ret        then liftIO (writeIORef brkRef False) >> pure False        else boolValue mCond<\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0446\u0438\u043a\u043b\u0430 while \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"haskell\">    While mCond mBody -> while (whileCond mCond) mBody >> pure Nothing<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e <code>Seq<\/code> \u2014 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434.<\/p>\n<pre><code class=\"haskell\">    Seq ss -> sequence_ ss >> pure Nothing<\/code><\/pre>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433 \u2014 \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u0443\u044e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/p>\n<pre><code class=\"haskell\">callFunction :: (MonadReader (Context m) m, MonadError m, MonadIO m)              => Text              -> [Value]              -> m (Maybe Value) callFunction fun args = do     -- \u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0442\u0435\u043b\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e \u0438\u043c\u0435\u043d\u0438, \u0435\u0441\u043b\u0438 \u043d\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u043c, \u043a\u0438\u0434\u0430\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.     funcs &lt;- asks ctxFunctions     case HashMap.lookup fun funcs of         Nothing    -> throwError $ \"undefined function \" &lt;> fun         Just fInfo -> call fInfo   where call (FuncInfo argNames body)           -- \u0415\u0441\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043d\u0435 \u0440\u0430\u0432\u043d\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443           -- \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0445, \u043a\u0438\u0434\u0430\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435           | actualNumArgs \/= expectedNumArgs           = throwError $  \"function \" &lt;> fun &lt;> \" expected \"                        &lt;> Text.pack (show expectedNumArgs)                        &lt;> \" arguments but given \"                        &lt;> Text.pack (show actualNumArgs)           | otherwise = do               -- \u0417\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438               -- \u0438 \u043f\u0438\u0448\u0435\u043c \u0432 ctxVariables \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f               -- \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438               let argsMap = HashMap.fromList $ zip argNames args               variablesRef &lt;- asks ctxVariables               backupVars &lt;- liftIO $ readIORef variablesRef               liftIO $ writeIORef variablesRef argsMap                          -- \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0442\u0435\u043b\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438               void body                -- \u0412\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u0430\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.               -- \u0421\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c ctxIsReturn, \u0434\u043e\u0441\u0442\u0430\u0451\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0439 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435               -- \u0438\u0437 ctxReturnValue \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0435\u0433\u043e               liftIO $ writeIORef variablesRef backupVars               returnValueRef &lt;- asks ctxReturnValue               isReturnRef &lt;- asks ctxIsReturn               returnValue &lt;- liftIO $ readIORef returnValueRef               liftIO $ do                   writeIORef returnValueRef Nothing                   writeIORef isReturnRef False                   pure returnValue            where actualNumArgs = length args                  expectedNumArgs = length argNames<\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u043d\u0438\u0436\u0435:<\/p>\n<pre><code class=\"haskell\">    Call fun mArgs -> do         args &lt;- anyValue (sequence &lt;$> sequence mArgs)         callFunction fun args<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0432\u043e\u0434-\u0432\u044b\u0432\u043e\u0434:<\/p>\n<pre><code class=\"haskell\">    Read -> do         str &lt;- liftIO Text.getLine         case Text.signed Text.decimal str of             Right (res, _) -> pure $ Just $ IntValue res             Left{}               | str == \"true\"  -> pure $ Just $ BoolValue True               | str == \"false\" -> pure $ Just $ BoolValue False               | otherwise      -> liftIO $ throwIO $                   InterpreterException \"failed to read value\"     Print args -> do         forM_ args $ \\case             StrArg str   -> liftIO $ Text.putStr str             ExprArg mVal -> mVal >>= \\case                 Just (IntValue i)  -> liftIO $ putStr $ show i                 Just (BoolValue b) -> liftIO $ Text.putStr $ if b                                                                 then \"true\"                                                                 else \"false\"                 Nothing            -> typeError \"int or bool\" \"unit\"         pure Nothing<\/code><\/pre>\n<p>\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438, \u043e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u0422\u0430\u043a\u0438\u0445 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0434\u0432\u0430 \u2014 \u043e\u0434\u0438\u043d \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043d\u0430\u0431\u0436\u0435\u043d\u044b \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439, \u0432\u0442\u043e\u0440\u043e\u0439 \u2014 \u0434\u043b\u044f \u0442\u0435\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435 \u0441\u043d\u0430\u0431\u0436\u0435\u043d\u044b:<\/p>\n<pre><code class=\"haskell\">interpretFunctions :: Text -> [Function Expr] -> IO () interpretFunctions = genericInterpretFunctions interpretExpr toIO   where toIO ctx ma = runReaderT (runInterpreterM ma) ctx  interpretPosFunctions :: Text -> [Function PosExpr] -> IO () interpretPosFunctions = genericInterpretFunctions interpretPosExpr toIO   where toIO ctx ma = runReaderT (runPosInterpreterM ma) ctx  genericInterpretFunctions :: (MonadReader (Context m) m, MonadError m, MonadIO m)                           => (e -> m (Maybe Value))                           -> (Context m -> m (Maybe Value) -> IO (Maybe Value))                           -> Text                           -> [Function e]                           -> IO () genericInterpretFunctions eval toIO sourceCode funDefs = do     variables &lt;- newIORef HashMap.empty     isBreak &lt;- newIORef False     isReturn &lt;- newIORef False     retValue &lt;- newIORef Nothing     let ctx = Context             { ctxVariables   = variables             , ctxFunctions   = functions             , ctxSourceSpan  = SourceSpan initPos initPos             , ctxSourceCode  = sourceCode             , ctxIsBreak     = isBreak             , ctxIsReturn    = isReturn             , ctxReturnValue = retValue             }     void $ toIO ctx (callFunction \"main\" [])   where initPos = SourcePos \"\" 1 1         functions = foldl collectFunction HashMap.empty funDefs         collectFunction funcs (Function name args body) =             HashMap.insert name func funcs           where func = FuncInfo args (eval body)<\/code><\/pre>\n<h3>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0451 \u0432\u043c\u0435\u0441\u0442\u0435<\/h3>\n<p>\u0412\u0441\u0435 \u0447\u0430\u0441\u0442\u0438 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0438\u0445 \u0432\u043c\u0435\u0441\u0442\u0435:<\/p>\n<pre><code class=\"haskell\">module Main (main) where  import System.Environment (getArgs, getProgName) import System.Exit        (die)  import Lang.Ast    (interpretPosFunctions) import Lang.Parser (parseFromText)  import qualified Data.Text.IO as Text  main :: IO () main = do     fileName &lt;- getFileName     sourceCode &lt;- Text.readFile fileName     case parseFromText fileName sourceCode of         Left err -> Text.putStrLn err         Right fs -> interpretPosFunctions sourceCode fs   where getFileName = getArgs >>= \\case             [x] -> pure x             _   -> do                 progName &lt;- getProgName                 die $ \"Usage: \" ++ progName ++ \" &lt;file.lang>\"<\/code><\/pre>\n<p>\u0418\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u043a\u043e\u0434 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/ci.cyberfined.xyz\/cyberfined\/fix-lang\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>.<\/p>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u044b \u0438\u043c\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 \u043d\u0435 \u0441\u0430\u043c\u044b\u043c \u043b\u0443\u0447\u0448\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0441\u0432\u0451\u0440\u0442\u043a\u0438. \u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 break \u0438 return \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0445\u0430\u043a \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 \u0444\u043b\u0430\u0433\u043e\u0432 <code>ctxIsBreak<\/code> \u0438 <code>ctxIsReturn<\/code> \u0438 \u0438\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u043a\u0430\u0436\u0434\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438. \u0414\u043b\u044f \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u0438\u044f \u0442\u0435\u043c\u044b \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0438\u043c\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e, \u043a\u0430\u043a \u0431\u043e\u043b\u0435\u0435 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u0439 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u043e\u043b\u0435\u0435 \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430, \u043c\u043e\u0433\u0443 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0442\u0438\u043f\u043e\u0432, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043c\u043d\u043e\u0439 \u0434\u043b\u044f \u0434\u0432\u0443\u0445 \u044f\u0437\u044b\u043a\u043e\u0432: <a href=\"https:\/\/ci.cyberfined.xyz\/cyberfined\/harakiri-lib\/src\/branch\/master\/src\/Harakiri\/TypeCheck.hs\" rel=\"noopener noreferrer nofollow\">harakiri<\/a> \u0438 <a href=\"https:\/\/ci.cyberfined.xyz\/cyberfined\/higer\/src\/branch\/master\/src\/Tiger\/TypeCheck.hs\" rel=\"noopener noreferrer nofollow\">tiger<\/a>, <a href=\"https:\/\/ci.cyberfined.xyz\/cyberfined\/harakiri-lib\/src\/branch\/master\/src\/Harakiri\/IR\/Translate.hs\" rel=\"noopener noreferrer nofollow\">\u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u044e<\/a> \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430 \u044f\u0437\u044b\u043a\u0430 harakiri \u0432 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u043f\u0440\u043e\u0435\u043a\u0442 <a href=\"https:\/\/github.com\/haskell-nix\/hnix\" rel=\"noopener noreferrer nofollow\">hnix<\/a>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f nix.<\/p>\n<\/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\/post\/667058\/\"> https:\/\/habr.com\/ru\/post\/667058\/<\/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<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\u00a0\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u043e\u0439 \u0441\u0432\u0451\u0440\u0442\u043a\u0438. \u0414\u0430\u043b\u0435\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0443\u0436\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u00a0\u0441 \u0442\u0438\u043f\u043e\u043c <code>Fix<\/code> &#8212; \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0442\u043e\u0440\u043e\u0432, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c <a href=\"#main\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0438<\/a>.<\/p>\n<h3>\u041f\u0440\u0430\u0432\u0430\u044f \u0441\u0432\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u0441\u043f\u0438\u0441\u043a\u043e\u0432<\/h3>\n<p>\u0421\u0432\u0451\u0440\u0442\u043a\u0430 \u2014 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0442\u0438\u043f\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0434\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0447\u0438\u0441\u0435\u043b \u0432 \u0438\u0445 \u0441\u0443\u043c\u043c\u0443, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0441\u0430\u043c\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u043a\u0430\u043a \u0431\u044b \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u0442\u0441\u044f. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c\u00a0\u043f\u0440\u0430\u0432\u0443\u044e \u0441\u0432\u0451\u0440\u0442\u043a\u0443 \u0434\u043b\u044f \u0441\u043f\u0438\u0441\u043a\u0430:<\/p>\n<pre><code class=\"haskell\">foldr :: (a -> b -> b) -> b -> [a] -> b foldr f ini (x:xs) = f x (foldr f ini xs) foldr _ ini _      = ini<\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>f<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u00a0\u0441\u043f\u0438\u0441\u043a\u0430, \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432 \u043d\u0435\u0439 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u043e\u0431\u0445\u043e\u0434 \u0441\u043f\u0438\u0441\u043a\u0430. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432 <code>foldr<\/code>\u00a0\u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0445\u043e\u0434 \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u0432\u044b\u0437\u043e\u0432 \u043d\u0430\u0448\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0435\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u043d\u0430\u043c \u0436\u0435 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u00a0\u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443. \u0412\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u2014 \u043c\u043e\u0436\u0435\u043c \u043b\u0438 \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0443\u044e <code>foldr<\/code>,\u00a0 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u041e\u0442\u0432\u0435\u0442 \u2014 \u0434\u0430, \u043c\u043e\u0436\u0435\u043c. \u041a\u0430\u043a, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u00a0\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u0445.<\/p>\n<h3>\u0422\u0438\u043f Fix<\/h3>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043f\u0438\u0441\u043e\u043a \u0438 \u0432\u044b\u0434\u0435\u043b\u0438\u043c \u043d\u0430 \u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0431\u0449\u0438\u0439 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0445\u00a0\u0442\u0438\u043f\u043e\u0432 \u043f\u0430\u0442\u0442\u0435\u0440\u043d.<\/p>\n<pre><code class=\"haskell\">data List a = Nil | Elem a (List a)<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0443\u0431\u0440\u0430\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438\u0437 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u0438\u043f\u0430:<\/p>\n<pre><code class=\"haskell\">data List a b = Nil | Elem a b<\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u0434\u0432\u0443\u043c\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438:<\/p>\n<pre><code class=\"haskell\">xs = Elem 1 (Elem 2 Nil)<\/code><\/pre>\n<p>\u041f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e! \u0423 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u2014 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u043b\u0438\u0448\u0435\u043d\u043e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438. \u041d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u043d\u043e \u043d\u043e \u2014 <code>xs<\/code> \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f \u043d\u0435 <code>List Int<\/code>, \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0436\u0434\u0435, \u0430 <code>List Int (List Int (List Int a))<\/code>. \u0422\u043e \u0435\u0441\u0442\u044c\u00a0\u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c, \u0438\u043c\u0435\u044e\u0449\u0438\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440. \u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u00a0\u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0442\u0438\u043f \u0441 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439.<\/p>\n<pre><code class=\"haskell\">newtype Fix f = Fix { unFix :: f (Fix f) }<\/code><\/pre>\n<p>\u0420\u0430\u043d\u044c\u0448\u0435 \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>b<\/code> \u0432 \u0442\u0438\u043f\u0435 <code>List<\/code> \u043c\u044b \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u043b\u0438 <code>List a<\/code>, \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u043b\u0438 \u043c\u044b\u00a0\u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>List a<\/code> \u0432 <code>Fix<\/code>, \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 <code>Fix<\/code> \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0437\u0430 \u043d\u0430\u0441:<\/p>\n<pre><code class=\"haskell\">type FixedList a = Fix (List a)<\/code><\/pre>\n<p>\u0421\u043d\u043e\u0432\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u0434\u0432\u0443\u043c\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438:<\/p>\n<pre><code class=\"haskell\">xs :: FixedList Int xs = Fix (Elem 1 (Fix (Elem 2 (Fix Nil))))<\/code><\/pre>\n<p>\u041c\u043e\u0436\u043d\u043e \u0440\u0430\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u2014 \u043c\u044b \u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438\u0437 \u0442\u0438\u043f\u0430 \u0443\u0431\u0440\u0430\u043b\u0438 \u0438 \u0442\u0438\u043f \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432 \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432\u00a0\u0432 \u0441\u043f\u0438\u0441\u043a\u0435. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043a \u043b\u044e\u0431\u043e\u043c\u0443 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u043c\u0443 \u0442\u0438\u043f\u0443, \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0432\u00a0\u0435\u0433\u043e \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043d\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u0438\u043f\u0430.<\/p>\n<h4>\u041f\u0438\u0448\u0435\u043c \u0441\u0432\u0451\u0440\u0442\u043a\u0443 \u0434\u043b\u044f Fix<\/h4>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u0438\u043f\u0430 <code>List<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0432\u0435\u043b\u0438, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f, \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043a\u043b\u0435\u0439\u043a\u0438 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u0432\u0441\u0435\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0441\u043f\u0438\u0441\u043a\u0430 \u0441 \u0434\u0432\u0443\u043c\u044f\u00a0\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438. \u0414\u0430\u043b\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u043a\u043e\u0434 \u043d\u0430 \u043f\u0441\u0435\u0432\u0434\u043e\u0445\u0430\u0441\u043a\u0435\u043b\u0435, \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u00a0\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0441\u043f\u0438\u0441\u043a\u0430:<\/p>\n<pre><code class=\"haskell\">xs :: FixedList Int xs = Fix (Elem 1 (Fix (Elem 2 (Fix Nil))))<\/code><\/pre>\n<p><strong>\u041f\u0435\u0440\u0432\u044b\u0439 \u0448\u0430\u0433<\/strong><\/p>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c <code>Nil<\/code> \u0432 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443:<\/p>\n<pre><code class=\"haskell\">f :: List Int String -> String f Nil = \"\"<\/code><\/pre>\n<p><strong>\u0412\u0442\u043e\u0440\u043e\u0439 \u0448\u0430\u0433<\/strong><\/p>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0432 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430:<\/p>\n<pre><code class=\"haskell\">f :: List Int String -> String f (Elem 2 acc) = \"2\" ++ acc<\/code><\/pre>\n<p><strong>\u0422\u0440\u0435\u0442\u0438\u0439 \u0448\u0430\u0433<\/strong><\/p>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0432 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430:<\/p>\n<pre><code class=\"haskell\">f :: List Int String -> String f (Elem 1 acc) = \"1\" + acc<\/code><\/pre>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c &#171;12&#187;. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 <code>f<\/code> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043f\u0438\u0441\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c\u00a0\u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u043d\u0430\u0448\u0443 \u0441\u0432\u0451\u0440\u0442\u043a\u0443.<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0438\u0434\u0435\u044f \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0434\u043e\u043b\u0436\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0432\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u0442\u0438\u043f\u0430 <code>Fix<\/code> \u043f\u043e\u043d\u044f\u0442\u043d\u0430, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0435\u0451.<\/p>\n<pre><code class=\"haskell\">foldFix :: Functor f => (f a -> a) -> Fix f -> a foldFix f = f . fmap (foldFix f) . unFix<\/code><\/pre>\n<p>\u0422\u0438\u043f \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0444\u0443\u043d\u043a\u0442\u043e\u0440\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u043e\u043d\u0438\u043a\u0430\u0442\u044c \u0432 \u0435\u0433\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u0432\u0451\u0440\u0442\u043a\u0443, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043a\u043e\u043d\u0446\u0430.\u00a0<code>a<\/code> \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0438\u043f\u043e\u043c \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0442\u0435\u0445 \u043c\u0435\u0441\u0442\u0430\u0445, \u043a\u0443\u0434\u0430 \u043c\u044b \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u0438\u043f\u0430 \u0434\u043b\u044f \u0438\u0437\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438.<\/p>\n<h4>\u041f\u0438\u0448\u0435\u043c \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u043a\u0443 \u0434\u043b\u044f Fix<\/h4>\n<p>\u041f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u0442\u0438\u043f\u0430 <code>Fix<\/code>. \u0420\u0430\u0437\u0432\u0451\u0440\u0442\u043a\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442\u00a0\u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e:<\/p>\n<pre><code class=\"haskell\">unfoldFix :: Functor f => (a -> f a) -> a -> Fix f unfoldFix f = Fix . fmap (unfoldFix f) . f<\/code><\/pre>\n<h3>\u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c:<\/h3>\n<pre><code class=\"haskell\">{-# LANGUAGE DeriveFunctor #-}  module Main (main) where  import Prelude hiding (showList)  newtype Fix f = Fix { unFix :: f (Fix f) }  foldFix :: Functor f => (f a -> a) -> Fix f -> a foldFix f = f . fmap (foldFix f) . unFix  unfoldFix :: Functor f => (a -> f a) -> a -> Fix f unfoldFix f = Fix . fmap (unfoldFix f) . f  type List a = Fix (ListF a)  data ListF a b = Nil | Elem a b deriving Functor  showList :: Show a => List a -> String showList = foldFix showListF  showListF :: Show a => ListF a String -> String showListF Nil          = \"\" showListF (Elem x acc) = show x ++ acc  -- \u0421\u043f\u0438\u0441\u043e\u043a \u0447\u0438\u0441\u0435\u043b \u043e\u0442 0 \u0434\u043e 3 list :: List Int list = unfoldFix (\\x -> if x &lt;= 3 then Elem x (x + 1) else Nil) 0  -- \u0412\u044b\u0432\u0435\u0434\u0435\u0442 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c 0123 main :: IO () main = putStrLn $ showList list<\/code><\/pre>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439 \u0442\u0438\u043f <code>Fix<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0443\u0436\u0435\u00a0\u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432 \u043f\u0430\u043a\u0435\u0442\u0435 <a href=\"https:\/\/hackage.haskell.org\/package\/data-fix\" rel=\"noopener noreferrer nofollow\">data-fix<\/a>.<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440<\/h3>\n<p><a class=\"anchor\" name=\"main\" id=\"main\"><\/a><\/p>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u044e\u0431\u043e\u0433\u043e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u00a0\u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>foldFix<\/code> \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u044d\u0442\u043e\u043c \u0442\u0438\u043f\u0435 \u0432 \u043e\u0434\u043d\u043e. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043b\u044e\u0441\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e\u00a0\u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430 (\u0434\u0430\u043b\u0435\u0435 \u0410\u0421\u0414):<\/p>\n<ol>\n<li>\n<p> \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430 \u0431\u0435\u0437 \u044f\u0432\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442\u00a0\u043e\u0448\u0438\u0431\u043e\u043a, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u043c\u044b \u0437\u0430\u0431\u044b\u043b\u0438 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u043b\u0438\u0441\u0442\u043e\u0432 \u0434\u0435\u0440\u0435\u0432\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0 \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0432\u044b\u0437\u0432\u0430\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0435 <code>If<\/code> \u0434\u043b\u044f \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0438 <code>then<\/code> \u0431\u043b\u043e\u043a\u0430, \u0430 \u0434\u043b\u044f <code>else<\/code> \u0437\u0430\u0431\u044b\u043b\u0438. \u0422\u0430\u043a\u0436\u0435 \u044d\u0442\u043e\u00a0\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u0435\u043d\u0435\u0435 \u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434, \u0442\u0430\u043a \u043a\u0430\u043a \u044f\u0432\u043d\u043e\u0439 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438 \u0432 \u043a\u043e\u0434\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p> \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043d\u0430\u0431\u0434\u0438\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u043b\u0438\u0441\u0442 \u0434\u0435\u0440\u0435\u0432\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u0438 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0451 \u043d\u0430\u043b\u0438\u0447\u0438\u0435.\u00a0 \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u043b\u0438\u0441\u0442 \u0434\u0435\u0440\u0435\u0432\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043d\u0430\u0431\u0436\u0451\u043d \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0430\u0439\u043b\u0430 \u0441 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043e\u0439, \u0447\u0442\u043e\u00a0 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u043e\u0439, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430.<\/p>\n<h4>\u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441<\/h4>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441 \u0442\u0438\u043f\u043e\u043c int \u0438 bool, \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 if, \u0446\u0438\u043a\u043b while \u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0435\u00a0\u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u043d\u0438\u0436\u0435:<\/p>\n<pre><code>def fac_rec(x) {     if x == 2 {         return x     } else {         return x * fac_rec(x - 1)     } }  def fac_iter(x) {     res = 1     while x >= 2 {         res = x * res         x = x - 1     }     return res }  def main() {     while true {         print(\"Enter mode:\\n1) recursive\\n2) iterative\\n3) exit\\n\")         mode = read()         if mode == 1 || mode == 2 {             print(\"Enter x: \")             x = read()             res = 0             if mode == 1 {                 res = fac_rec(x)             } else {                 res = fac_iter(x)             }             print(\"x!: \", res, \"\\n\")         } else {             if mode == 3 {                 break             } else {                 print(\"mode is invalid\\n\")             }         }     } }<\/code><\/pre>\n<h4>\u0410\u0421\u0414<\/h4>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u0442\u0438\u043f \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0410\u0421\u0414:<\/p>\n<pre><code class=\"haskell\">data Function = Function     { funName :: Text     , funArgs :: [Text]     , funBody :: Expr     } deriving Eq  data Expr     = IntLit Int     | BoolLit Bool     | Var Text     | UnOp UnOp Expr     | BinOp BinOp Expr Expr     | Assign Text Expr     | If Expr Expr (Maybe Expr)     | While Expr Expr     | Seq [Expr]     | Call Text [Expr]     | Break     | Read     | Print [PrintArg]     | Return (Maybe Expr)     deriving Eq  data UnOp = Neg | Not deriving Eq  data BinOp     = Add | Sub | Mul | Div     | Lt | Le | Gt | Ge     | Eq | Ne | And | Or     deriving Eq  data PrintArg     = StrArg Text     | ExprArg Expr     deriving Eq<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u0443\u0431\u0435\u0440\u0451\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432:<\/p>\n<pre><code class=\"haskell\">module Lang.Ast.Types where  data Function b = Function     { funName :: Text     , funArgs :: [Text]     , funBody :: b     } deriving (Eq, Functor, Foldable, Traversable)  type Expr = Fix ExprF  data ExprF a     = IntLit Int     | BoolLit Bool     | Var Text     | UnOp UnOp a     | BinOp BinOp a a     | Assign Text a     | If a a (Maybe a)     | While a a     | Seq [a]     | Call Text [a]     | Break     | Read     | Print [PrintArg a]     | Return (Maybe a)     deriving (Functor, Foldable, Traversable)  data UnOp = Neg | Not deriving Eq  data BinOp     = Add | Sub | Mul | Div     | Lt | Le | Gt | Ge     | Eq | Ne | And | Or     deriving Eq  data PrintArg a     = StrArg Text     | ExprArg a     deriving (Functor, Foldable, Traversable)<\/code><\/pre>\n<h4>\u0421\u043d\u0430\u0431\u0436\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u043b\u0438\u0441\u0442 \u0410\u0421\u0414 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439 \u0432 \u0444\u0430\u0439\u043b\u0435<\/h4>\n<pre><code class=\"haskell\">module Lang.Ast.Annotated where  -- \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0441\u043d\u0430\u0431\u0436\u0451\u043d\u043d\u043e\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439 type PosExpr = Fix PosExprF  type PosExprF = AnnF SourceSpan ExprF  -- \u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0442\u043e\u0440\u0430 f \u0441 \u0444\u0443\u043d\u043a\u0442\u043e\u0440\u043e\u043c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 type AnnF ann f = Compose (Ann ann) f  -- \u0424\u0443\u043d\u043a\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u0435\u0433\u043e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e data Ann ann a = Ann     { annotation :: ann     , annotated  :: a     } deriving (Functor, Foldable, Traversable)  -- \u041d\u0430\u0447\u0430\u043b\u043e \u0438 \u043a\u043e\u043d\u0435\u0446 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 data SourceSpan = SourceSpan     { spanBegin :: SourcePos     , spanEnd   :: SourcePos     } deriving (Eq, Show)  instance Semigroup SourceSpan where   s1 &lt;> s2 = SourceSpan ((min on spanBegin) s1 s2) ((max on spanEnd) s1 s2)  -- \u041f\u043e\u0437\u0438\u0446\u0438\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 data SourcePos = SourcePos     { posFile   :: FilePath     , posLine   :: Int     , posColumn :: Int     } deriving (Eq, Show)  instance Ord SourcePos where     compare (SourcePos _ b1 e1) (SourcePos _ b2 e2) =  compare b1 b2                                                     &lt;> compare e1 e2  -- \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0438\u0437 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430 stripAnnotation :: Functor f => Fix (AnnF ann f) -> Fix f stripAnnotation = unfoldFix (annotated . getCompose . unFix)<\/code><\/pre>\n<h4>\u0418\u043d\u0441\u0442\u0430\u043d\u0441 Eq<\/h4>\n<p>\u041d\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u0438\u043f\u0430 <code>Fix f<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u043b\u0430\u0441\u0441\u0430 <code>Eq<\/code>, \u0435\u0441\u043b\u0438\u00a0\u0434\u043b\u044f <code>f<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u043b\u0430\u0441\u0441\u0430 <code>Eq1<\/code>. \u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f <code>Eq1<\/code> \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432 <code>ExprF<\/code>, <code>PrintArg<\/code> \u0438 <code>Ann<\/code>.<\/p>\n<pre><code class=\"haskell\">import Data.Functor.Classes (Eq1(..))  instance Eq1 ExprF where     liftEq f a b = case (a, b) of     (IntLit i1, IntLit i2)                 -> i1 == i2     (BoolLit b1, BoolLit b2)               -> b1 == b2     (Var v1, Var v2)                       -> v1<\/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-333774","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/333774","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=333774"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/333774\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=333774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=333774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=333774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}