+module skeleton8\r
+\r
+import StdList, StdInt, Data.Tuple, StdClass, iTasks._Framework.Generic, Text.JSON, Data.Functor, Control.Applicative, Control.Monad, Data.Void\r
+import qualified iTasks\r
+import qualified Text\r
+from Text import class Text, instance Text String\r
+from StdFunc import o\r
+from StdTuple import fst\r
+from Data.Map import :: Map, put, get, newMap\r
+import Data.Either\r
+import qualified Data.List as List\r
+\r
+:: Element :== Sem Int\r
+:: Set :== Sem [Int]\r
+:: Val = I Int | S [Int] | B Bool\r
+:: State :== Map String Val\r
+:: Sem a = Sem (State -> (Either String a, State)) \r
+\r
+instance Functor Sem where\r
+ fmap :: (a -> b) (Sem a) -> Sem b\r
+ fmap f (Sem s) = Sem \st.let (a, st`) = s st in (fmap f a, st`)\r
+\r
+instance Applicative Sem where\r
+ pure :: a -> Sem a\r
+ pure s = Sem \st.(pure s, st)\r
+ (<*>) infixl 4 :: (Sem (a -> b)) (Sem a) -> Sem b\r
+ (<*>) a f = ap a f\r
+\r
+instance Monad Sem where\r
+ bind :: (Sem a) (a -> Sem b) -> Sem b\r
+ bind (Sem s) f = Sem \st.case s st of\r
+ (Right v, st`) = let (Sem r) = f v in r st`\r
+ (Left e, st`) = (Left e, st`)\r
+\r
+fail :: String -> Sem a\r
+fail s = Sem \st.(Left s,st)\r
+\r
+instance + Element where (+) s1 s2 = (+) <$> s1 <*> s2\r
+instance - Element where (-) s1 s2 = (-) <$> s1 <*> s2\r
+instance * Element where (*) s1 s2 = (*) <$> s1 <*> s2\r
+\r
+integer :: Int -> Element\r
+integer i = return i\r
+\r
+size :: Set -> Element\r
+size s = length <$> s\r
+\r
+new :: Set\r
+new = return []\r
+\r
+insert :: Element Set -> Set\r
+insert e s = union ((\x.[x]) <$> e) s\r
+\r
+delete :: Element Set -> Set\r
+delete e s = difference ((\x.[x]) <$> e) s\r
+\r
+union :: Set Set -> Set\r
+union s1 s2 = fmap 'List'.union s1 <*> s2\r
+\r
+difference :: Set Set -> Set\r
+difference s1 s2 = fmap 'List'.difference s1 <*> s2\r
+\r
+intersection :: Set Set -> Set\r
+intersection s1 s2 = fmap 'List'.intersect s1 <*> s2\r
+\r
+class eval a :: (Sem a) -> (Either String a, State)\r
+\r
+instance eval Element where\r
+ eval (Sem e) = e newMap\r
+\r
+instance eval Set where\r
+ eval (Sem s) = s newMap\r
+\r
+instance eval Int where\r
+ eval (Sem s) = s newMap\r
+\r
+instance eval [Int] where\r
+ eval (Sem s) = s newMap\r
+\r
+class variable a :: String -> a\r
+\r
+instance variable Element where\r
+ variable k = Sem \st.case get k st of\r
+ (Just (I v)) = (Right v, st)\r
+ (Just _) = (Left "Wrong type, expected Int", st)\r
+ _ = (Left "Variable not found", st)\r
+\r
+instance variable Set where\r
+ variable k = Sem \st.case get k st of\r
+ (Just (S v)) = ((Right v), st)\r
+ (Just _) = (Left "Wrong type, expected Set", st)\r
+ _ = (Left "Variable not found", st)\r
+\r
+class (=.) infix 2 a :: String a -> a\r
+\r
+instance =. Element where\r
+ (=.) k (Sem v) = Sem \st.case v st of\r
+ (Right v, st) = (Right v, put k (I v) st)\r
+ (Left e, st) = (Left e, st)\r
+\r
+instance =. Set where\r
+ (=.) k (Sem v) = Sem \st.case v st of\r
+ (Right v, st) = (Right v, put k (S v) st)\r
+ (Left e, st) = (Left e, st)\r
+\r
+(:.) infixl 1 :: (Sem a) (Sem b) -> (Sem b)\r
+(:.) s1 s2 = s1 >>| s2\r
+\r
+(==.) infix 4 :: (Sem a) (Sem a) -> (Sem Bool) | == a\r
+(==.) s1 s2 = fmap (==) s1 <*> s2\r
+\r
+(<.) infix 4 :: (Sem a) (Sem a) -> (Sem Bool) | < a\r
+(<.) s1 s2 = fmap (<) s1 <*> s2\r
+\r
+IF :: (Sem Bool) THEN (Sem a) ELSE (Sem a) -> Sem a\r
+IF c _ t _ e = c >>= \c.if c t e\r
+\r
+WHILE :: (Sem Bool) DO (Sem a) -> Sem Int\r
+WHILE c _ b = c >>= \c`.if c` (fmap ((+) 1) (b >>| WHILE c DO b)) (return 0)\r
+\r
+:: THEN = THEN\r
+:: ELSE = ELSE\r
+:: DO = DO\r
+\r
+// examples\r
+expr1 :: Element\r
+expr1 = integer 2\r
+\r
+expr2 :: Element\r
+expr2 = expr1 + expr1\r
+\r
+expr3 :: Element\r
+expr3 = expr1 + expr1 * integer 3\r
+\r
+expr4 :: Set\r
+expr4 = union new (insert expr1 (insert expr3 new))\r
+\r
+expr5 :: Set\r
+expr5 =\r
+ x =. expr4 :.\r
+ variable x\r
+\r
+expr6 :: Element\r
+expr6 =\r
+ x =. insert (integer 11) new :.\r
+ x =. size (variable x) :.\r
+ variable x\r
+\r
+expr7 :: Set\r
+expr7 =\r
+ x =. insert (integer 11) new :.\r
+ y =. variable x\r
+\r
+expr8 :: Set\r
+expr8 =\r
+ x =. insert (integer 11) new :.\r
+ x =. insert (size (variable x)) (variable x) :.\r
+ variable x\r
+\r
+expr9 :: Set\r
+expr9 =\r
+ x =. insert (integer 0) new :.\r
+ IF (size (variable x) ==. integer 0) THEN\r
+ (x =. insert (integer 0) (variable x))\r
+ ELSE\r
+ (x =. delete (integer 0) (variable x)) :.\r
+ variable x\r
+\r
+expr10 :: Set\r
+expr10 =\r
+ z =. integer 7 :.\r
+ x =. new :.\r
+ x =. insert (variable z) (variable x) :.\r
+ y =. union (variable x) (variable x) :.\r
+ WHILE (size (variable x) <. integer 5) DO\r
+ (x =. insert (size (variable x)) (variable x)) :.\r
+ z =. difference (variable x) (intersection (variable x) (insert (variable z) new))\r
+\r
+x = "x"\r
+y = "y"\r
+z = "z"\r
+\r
+Start = expr10\r