123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- 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
|