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