|
@@ -0,0 +1,135 @@
|
|
|
+import Control.Applicative
|
|
|
+import Control.Monad
|
|
|
+import Control.Monad.State
|
|
|
+
|
|
|
+-- Logger
|
|
|
+type Log = [String]
|
|
|
+newtype Logger a = Logger {runLogger :: (a, Log)}
|
|
|
+
|
|
|
+--Let's define Log an instance of Show
|
|
|
+instance (Show a) => Show (Logger a ) where
|
|
|
+ show (Logger a) = show a
|
|
|
+
|
|
|
+--Define an instance of Functor for Logger
|
|
|
+loggerMap :: (a -> b) -> Logger a -> Logger b
|
|
|
+loggerMap f lg =
|
|
|
+ let (v, l) = runLogger lg
|
|
|
+ n = f v
|
|
|
+ in Logger (n, l)
|
|
|
+
|
|
|
+instance Functor Logger where
|
|
|
+ fmap = loggerMap
|
|
|
+
|
|
|
+loggerApp :: Logger (a -> b) -> Logger a -> Logger b
|
|
|
+loggerApp lf lg =
|
|
|
+ let (f, s) = runLogger lf
|
|
|
+ nl = loggerMap f lg
|
|
|
+ (n, l) = runLogger nl
|
|
|
+ in Logger (n, l ++ s)
|
|
|
+
|
|
|
+instance Applicative Logger where
|
|
|
+ pure x = Logger (x, [])
|
|
|
+ (<*>) = loggerApp
|
|
|
+
|
|
|
+--Define the Logger Monad
|
|
|
+
|
|
|
+instance Monad Logger where
|
|
|
+ m >>= f = let (a, w) = runLogger m
|
|
|
+ n = f a
|
|
|
+ (b, x) = runLogger n
|
|
|
+ in Logger (b, w ++ x)
|
|
|
+
|
|
|
+--Define a function that takes a number, add one and log the operation
|
|
|
+logPlusOne :: (Num a) => a -> Logger a
|
|
|
+logPlusOne a = Logger (a+1, ["added one"])
|
|
|
+
|
|
|
+--Define a function that takes a number, doubles it and log the operation
|
|
|
+logMultiplyTwo :: (Num a) => a -> Logger a
|
|
|
+logMultiplyTwo a = Logger (a*2, ["Multiplied by two"])
|
|
|
+
|
|
|
+--Define a function that takes a logger, adds one, double the value and logs all the operations
|
|
|
+logOps :: (Num a) => a -> Logger a
|
|
|
+logOps a = pure a >>= logPlusOne >>= logMultiplyTwo
|
|
|
+
|
|
|
+logOps' :: (Num a) => Logger a -> Logger a
|
|
|
+logOps' a = do
|
|
|
+ v <- a
|
|
|
+ s1 <- logPlusOne v
|
|
|
+ p2 <- logMultiplyTwo s1
|
|
|
+ return p2
|
|
|
+
|
|
|
+--Define a record function to record things in the logPlusOne
|
|
|
+record :: String -> Logger ()
|
|
|
+record s = Logger ((), [s])
|
|
|
+
|
|
|
+--Define a binary Tree
|
|
|
+data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Eq, Read)
|
|
|
+
|
|
|
+treeFoldr :: (b -> a -> a) -> a -> Tree b -> a
|
|
|
+treeFoldr f acc EmptyTree = acc
|
|
|
+treeFoldr f acc (Node a left right) = treeFoldr f (f a (treeFoldr f acc right)) left
|
|
|
+
|
|
|
+singletonM :: (Show a) => a -> Logger (Tree a)
|
|
|
+singletonM x = do
|
|
|
+ record ("Created singleton" ++ show x)
|
|
|
+ return (Node x EmptyTree EmptyTree)
|
|
|
+
|
|
|
+treeInsertM :: (Ord a, Show a) => Tree a -> a -> Logger (Tree a)
|
|
|
+treeInsertM EmptyTree x = singletonM x
|
|
|
+treeInsertM (Node a left right) x
|
|
|
+ | x == a = do
|
|
|
+ record("Inserted " ++ show x)
|
|
|
+ return (Node x left right)
|
|
|
+ | x < a = do
|
|
|
+ l <- treeInsertM left x
|
|
|
+ return (Node a l right)
|
|
|
+ | x > a = do
|
|
|
+ r <- treeInsertM right x
|
|
|
+ return (Node a left r)
|
|
|
+treeSumM :: (Num a) => Logger (Tree a) -> Logger a
|
|
|
+treeSumM t = fmap (treeFoldr (+) 0) t
|
|
|
+
|
|
|
+andM :: Logger Bool -> Logger Bool -> Logger Bool
|
|
|
+andM log1 log2 = do
|
|
|
+ c1 <- log1
|
|
|
+ c2 <- log2
|
|
|
+ return (c1 && c2)
|
|
|
+
|
|
|
+treeBalancedM :: Tree a -> Logger Bool
|
|
|
+treeBalancedM EmptyTree = do
|
|
|
+ record "an empty tree is always balanced"
|
|
|
+ return True
|
|
|
+treeBalancedM (Node _ EmptyTree EmptyTree) = do
|
|
|
+ record "A single node tree is always balanced"
|
|
|
+ return True
|
|
|
+treeBalancedM (Node _ EmptyTree _) = do
|
|
|
+ record "Unbalanced"
|
|
|
+ return False
|
|
|
+treeBalancedM (Node _ _ EmptyTree) = do
|
|
|
+ record "Unbalanced"
|
|
|
+ return False
|
|
|
+treeBalancedM (Node _ left right) = andM (treeBalancedM left) (treeBalancedM right)
|
|
|
+
|
|
|
+type Stack = [Int]
|
|
|
+
|
|
|
+--Define the pop function
|
|
|
+pop :: Stack -> (Int, Stack)
|
|
|
+pop (x:xs) = (x, xs)
|
|
|
+
|
|
|
+--Define the push function
|
|
|
+push :: Int -> Stack -> ((), Stack)
|
|
|
+push x xs = ((), x:xs)
|
|
|
+
|
|
|
+stackManip :: Stack -> (Int, Stack)
|
|
|
+stackManip stack = let
|
|
|
+ (a, stack1) = pop stack
|
|
|
+ (b, stack2) = pop stack1
|
|
|
+ ((), stack3) = push 100 stack2
|
|
|
+ (c, stack4) = pop stack3
|
|
|
+ in pop stack4
|
|
|
+
|
|
|
+popM :: State Stack Int
|
|
|
+popM = do
|
|
|
+ x:xs <- get
|
|
|
+ put xs
|
|
|
+ return x
|