module serialize4 // Laurens Kuiper (s4467299) // Camil Staps (s4498062) // Output: // Oke; True // Oke; False // Oke; 0 // Oke; 123 // Oke; -36 // Oke; (Cons 42 Nil) // Oke; (Cons 0 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil))))) // Oke; (Cons (Cons True Nil) (Cons Nil Nil)) // Oke; (Cons (Cons (Cons 1 Nil) Nil) (Cons (Cons (Cons 2 Nil) (Cons (Cons 3 (Cons 4 Nil)) Nil)) (Cons (Cons Nil Nil) Nil))) // Oke; (Cons (Cons True Nil) (Cons Nil Nil)) // Oke; (Bin Leaf True Leaf) // Oke; (Cons (Bin (Bin Leaf (Cons 1 Nil) Leaf) (Cons 2 Nil) (Bin Leaf (Cons 3 Nil) (Bin Leaf (Cons 4 (Cons 5 Nil)) Leaf))) Nil) // Oke; (Cons (Bin (Bin Leaf (Cons 1 Nil) Leaf) (Cons 2 Nil) (Bin Leaf (Cons 3 Nil) (Bin (Bin Leaf (Cons 4 (Cons 5 Nil)) Leaf) (Cons 6 (Cons 7 Nil)) (Bin Leaf (Cons 8 (Cons 9 Nil)) Leaf)))) Nil) // Oke; Head // Oke; Tail // Oke; (7,True) // Oke; (Head,(7,(Cons Tail Nil))) // End of the tests. import StdEnv, StdMaybe, monad appFst :: (a -> c) (a, b) -> (c, b) appFst f (x,y) = (f x, y) /* * Pieter Koopman, pieter@cs.ru.nl * Advanced Programming, week 4, 2017 * * import StdMaybe from Libraries/StdLib * use StdEnv or StdEnv 64 * use Basic Values Only as conclose option for a nicer output. */ // --- instance Functor Maybe where fmap f (Just x) = Just (f x) fmap _ Nothing = Nothing instance Applicative Maybe where pure x = Just x (<*>) (Just f) (Just x) = Just (f x) (<*>) _ _ = Nothing :: State s a = S (s -> (Maybe a,s)) unS :: (State s a) -> s -> (Maybe a,s) unS (S f) = f instance Functor (State s) where fmap f (S s) = S \st -> appFst (fmap f) (s st) instance Applicative (State s) where pure x = S \s -> (pure x,s) (<*>) (S f) (S x) = S \st -> let (f`,st`) = f st; (x`,st``) = x st` in (f` <*> x`, st``) instance fail (State s) where fail = S \s -> (Nothing,s) instance Monad (State s) where bind (S x) f = S \st -> case x st of (Just x, st) -> unS (f x) st (Nothing,st) -> (Nothing,st) instance OrMonad (State s) where (<|>) (S f) (S g) = S \s -> case f s of r=:(Just _,_) -> r _ -> g s // --- :: Serialized :== [String] ser :: Serialized ser = [] :: Serialize a :== State Serialized a wrt :: a -> Serialize String | toString a wrt x = S \s -> let x` = toString x in (pure x`, [x`:s]) rd :: Serialize String rd = S \s -> case s of [] -> (Nothing, s) [s:ss] -> (Just s, ss) pred :: (String->Bool) -> Serialize String pred f = rd >>= \x -> if (f x) (pure x) fail match :: a -> Serialize a | toString a match x = pred ((==) (toString x)) >>| pure x // --- :: UNIT = UNIT :: EITHER a b = LEFT a | RIGHT b :: PAIR a b = PAIR a b :: CONS a = CONS String a :: Write a :== a -> Serialize String :: Read a :== Serialize a class serialize a where write :: a -> Serialize String read :: Serialize a class serialize1 t where write1 :: (Write a) (t a) -> Serialize String read1 :: (Read a) -> Serialize (t a) class serializeCONS a where writeCons :: (Write a) (CONS a) -> Serialize String readCons :: String (Read a) -> Serialize (CONS a) class serialize2 t where write2 :: (Write a) (Write b) (t a b) -> Serialize String read2 :: (Read a) (Read b) -> Serialize (t a b) instance serialize Bool where write b = wrt b read = match True <|> match False instance serialize Int where write i = wrt i read = rd >>= safeToInt where safeToInt :: String -> m Int | fail, Applicative m safeToInt "0" = pure 0 safeToInt s = case toInt s of 0 -> fail; n -> pure n instance serialize String where write s = wrt s read = rd instance serialize UNIT where write _ = pure "" read = pure UNIT instance serializeCONS UNIT where writeCons wa (CONS name a) = wrt name readCons name ra = match name >>| pure (CONS name UNIT) instance serializeCONS a where writeCons wa (CONS name a) = wrt ")" >>| wa a >>| write " " >>| wrt name >>| wrt "(" readCons name ra = match "(" >>| match name >>| match " " >>| ra >>= \a -> match ")" >>| pure (CONS name a) instance serialize2 EITHER where write2 wa wb (LEFT a) = wa a write2 wa wb (RIGHT b) = wb b read2 ra rb = LEFT <$> ra <|> RIGHT <$> rb instance serialize2 PAIR where write2 wa wb (PAIR a b) = wb b >>| wrt " " >>| wa a read2 ra rb = ra >>= \a -> match " " >>| rb >>= pure o PAIR a // --- :: ListG a :== EITHER (CONS UNIT) (CONS (PAIR a [a])) fromList :: [a] -> ListG a fromList [] = LEFT (CONS NilString UNIT) fromList [a:x] = RIGHT (CONS ConsString (PAIR a x)) toList :: (ListG a) -> [a] toList (LEFT (CONS NilString UNIT)) = [] toList (RIGHT (CONS ConsString (PAIR a x))) = [a:x] NilString :== "Nil" ConsString :== "Cons" instance serialize [a] | serialize a where write a = write1 write a read = read1 read instance serialize1 [] where write1 writea l = write2 (writeCons write) (writeCons (write2 writea (write1 writea))) (fromList l) read1 reada = toList <$> read2 (readCons NilString read) (readCons ConsString (read2 reada (read1 reada))) // --- :: Bin a = Leaf | Bin (Bin a) a (Bin a) :: BinG a :== EITHER (CONS UNIT) (CONS (PAIR (Bin a) (PAIR a (Bin a)))) fromBin :: (Bin a) -> BinG a fromBin Leaf = LEFT (CONS LeafString UNIT) fromBin (Bin l a r) = RIGHT (CONS BinString (PAIR l (PAIR a r))) toBin :: (BinG a) -> Bin a toBin (LEFT (CONS _ UNIT)) = Leaf toBin (RIGHT (CONS _ (PAIR l (PAIR a r)))) = Bin l a r LeafString :== "Leaf" BinString :== "Bin" instance == (Bin a) | == a where (==) Leaf Leaf = True (==) (Bin l a r) (Bin k b s) = l == k && a == b && r == s (==) _ _ = False instance serialize (Bin a) | serialize a where write b = write1 write b read = read1 read instance serialize1 Bin where write1 writea b = write2 (writeCons write) (writeCons (write2 (write1 writea) (write2 writea (write1 writea)))) (fromBin b) read1 reada = toBin <$> read2 (readCons LeafString read) (readCons BinString (read2 (read1 reada) (read2 reada (read1 reada)))) // --- :: Coin = Head | Tail :: CoinG :== EITHER (CONS UNIT) (CONS UNIT) fromCoin :: Coin -> CoinG fromCoin Head = LEFT (CONS "Head" UNIT) fromCoin Tail = RIGHT (CONS "Tail" UNIT) toCoin :: CoinG -> Coin toCoin (LEFT (CONS _ UNIT)) = Head toCoin (RIGHT (CONS _ UNIT)) = Tail instance == Coin where (==) Head Head = True (==) Tail Tail = True (==) _ _ = False instance serialize Coin where write c = write2 (writeCons write) (writeCons write) (fromCoin c) read = toCoin <$> read2 (readCons "Head" read) (readCons "Tail" read) // --- instance serialize (a,b) | serialize a & serialize b where write (a,b) = wrt ")" >>| write b >>| wrt "," >>| write a >>| wrt "(" read = match "(" >>| read >>= \a -> match "," >>| read >>= \b -> match ")" >>| pure (a,b) // --- Start = [ test True , test False , test 0 , test 123 , test -36 , test [42] , test [0..4] , test [[True],[]] , test [[[1]],[[2],[3,4]],[[]]] , test [[True],[]] , test (Bin Leaf True Leaf) , test [Bin (Bin Leaf [1] Leaf) [2] (Bin Leaf [3] (Bin Leaf [4,5] Leaf))] , test [Bin (Bin Leaf [1] Leaf) [2] (Bin Leaf [3] (Bin (Bin Leaf [4,5] Leaf) [6,7] (Bin Leaf [8,9] Leaf)))] , test Head , test Tail , test (7,True) , test (Head,(7,[Tail])) , ["End of the tests.\n"] ] test :: a -> [String] | serialize, == a test a = toStrings (snd ((unS t) ser)) where t = (write a >>| read >>= \b. guard (a == b) >>| write a >>| write "Oke; ") <|> write a >>| write "Failure: " <|> write "Failure (no write)" toStrings :: Serialized -> [String] toStrings xs = xs ++ ["\n"]