summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assignment-10/sets.icl125
1 files changed, 125 insertions, 0 deletions
diff --git a/assignment-10/sets.icl b/assignment-10/sets.icl
new file mode 100644
index 0000000..2a19584
--- /dev/null
+++ b/assignment-10/sets.icl
@@ -0,0 +1,125 @@
+module sets
+
+import StdBool
+import StdEnum
+from StdFunc import flip, o
+import StdGeneric
+import StdInt
+import StdList
+import StdString
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.State
+import Data.Error
+from Data.Func import $, on, `on`
+import Data.Functor
+import qualified Data.Map as M
+import Data.Maybe
+from Text import <+
+
+instance + [a] | Eq a where + xs ys = xs - ys ++ ys
+instance - [a] | Eq a where - xs ys = removeMembers xs ys
+instance * [a] | Eq a where * xs ys = [x \\ x <- xs | hasElem x ys]
+
+addElem :: a [a] -> [a] | Eq a
+addElem x xs = if (isMember x xs) xs [x:xs]
+
+removeElem :: (a [a] -> [a]) | Eq a
+removeElem = removeMember
+
+hasElem :: (a [a] -> Bool) | Eq a
+hasElem = isMember
+
+:: Expression a
+ = New (Bimap a [Int]) [Int]
+ | Elem (Bimap a Int) Int
+ | E.b: Variable (Bimap a b) Ident
+ | Size (Bimap a Int) Set
+ | (+.) infixl 6 (Expression a) (Expression a) & + a
+ | AddElemAndSet (Bimap a [Int]) Elem Set
+ | AddSetAndElem (Bimap a [Int]) Set Elem
+ | (-.) infixl 6 (Expression a) (Expression a) & - a
+ | RemoveFromSet (Bimap a [Int]) Set Elem
+ | (*.) infixl 7 (Expression a) (Expression a) & * a
+ | MulElemAndSet (Bimap a [Int]) Elem Set
+ | (=.) infixl 2 Ident (Expression a)
+
+ | Logical (Bimap a Bool) Bool
+ | Not (Bimap a Bool) Logical
+ | Or (Bimap a Bool) Logical Logical
+ | And (Bimap a Bool) Logical Logical
+ | In (Bimap a Bool) Elem Set
+ | E.b: Eq (Bimap a Bool) (Expression b) (Expression b) & TC, == b
+ | E.b: Le (Bimap a Bool) (Expression b) (Expression b) & TC, Ord b
+
+ | If Logical (Expression a) (Expression a)
+ | For (Bimap a [Int]) Ident Set (Expression Int)
+ | E.b: (:.) infixl 1 (Expression b) (Expression a) & TC b
+
+// Convenience
+new :== New bimapId
+elem :== Elem bimapId
+var :== Variable bimapId
+size :== Size bimapId
+for :== For bimapId
+
+(+:) infixl 6; (+:) :== AddSetAndElem bimapId
+(:+) infixl 6; (:+) :== AddElemAndSet bimapId
+(-:) infixl 6; (-:) :== RemoveFromSet bimapId
+(:*) infixl 7; (:*) :== MulElemAndSet bimapId
+
+:: SetState :== 'M'.Map Ident Dynamic
+:: Sem a :== StateT SetState (MaybeError String) a
+
+:: Set :== Expression [Int]
+:: Elem :== Expression Int
+:: Logical :== Expression Bool
+:: Ident :== String
+
+store :: Ident v -> StateT SetState m v | Monad m & TC v
+store i v = modify ('M'.put i (dynamic v)) $> v
+
+read :: Ident -> StateT SetState (MaybeError String) v | TC v
+read i = gets ('M'.get i) >>= \v -> case v of
+ Just (x :: v^) -> pure x
+ Just d -> fail $ "type error, " <+ typeCodeOfDynamic d <+ " for '" <+ i <+ "'"
+ Nothing -> fail $ "unknown variable '" <+ i <+ "'"
+
+fail :: String -> StateT s (MaybeError String) a
+fail e = StateT \_ -> Error e
+
+eval :: (Expression a) -> Sem a | TC a
+eval (New bm xs) = pure $ bm.map_from xs
+eval (Elem bm x) = pure $ bm.map_from x
+eval (Variable bm id) = read id
+eval (Size bm s) = bm.map_from <$> length <$> eval s
+eval (+. x y) = (liftA2 (+) `on` eval) x y
+eval (AddElemAndSet bm e s) = bm.map_from <$> liftA2 addElem (eval e) (eval s)
+eval (AddSetAndElem bm s e) = bm.map_from <$> liftA2 addElem (eval e) (eval s)
+eval (-. x y) = (liftA2 (-) `on` eval) x y
+eval (RemoveFromSet bm s e) = bm.map_from <$> liftA2 removeElem (eval e) (eval s)
+eval (*. x y) = (liftA2 (*) `on` eval) x y
+eval (MulElemAndSet bm e s) = bm.map_from <$> liftA2 (map o (*)) (eval e) (eval s)
+eval (=. id e) = eval e >>= store id
+eval (Logical bm b) = pure $ bm.map_from b
+eval (Not bm l) = bm.map_from <$> not <$> eval l
+eval (Or bm x y) = bm.map_from <$> (liftA2 (||) `on` eval) x y
+eval (And bm x y) = bm.map_from <$> (liftA2 (&&) `on` eval) x y
+eval (In bm e s) = bm.map_from <$> liftA2 hasElem (eval e) (eval s)
+eval (Eq bm x y) = bm.map_from <$> liftA2 (==) (eval x) (eval y)
+eval (Le bm x y) = bm.map_from <$> liftA2 (<=) (eval x) (eval y)
+eval (If b t e) = eval b >>= \b -> eval $ if b t e
+eval (For bm id s e) = bm.map_from <$> (eval s >>= mapM (\x -> store id x >>| eval e))
+eval (s :. t) = eval s >>| eval t
+
+Start = evalStateT (eval stmt) 'M'.newMap
+where
+ stmt :: Expression [Int]
+ stmt =
+ "x" =. new [3..10] :.
+ "y" =. elem 0 :.
+ elem 10 :* for "i" (new [1..5] +. var "x") (
+ "y" =. var "y" +. elem 1 :.
+ var "i" *. var "y"
+ )