module EsHs4 where import Control.Applicative import Control.Monad --Logger type Log = [String] newtype Logger a = Logger { runLogger :: (a, Log) } --Define an instance of Show for Logger instance Show a => Show (Logger a) where show (Logger a) = show a --Define an instance of Functor for logger class Functor f where fmap :: (a -> b) -> f a -> f b 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 a = Logger (a, []) (<*>) = loggerApp 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 op: logPlusOne :: (Num a) => a -> Logger a logPlusOne a = Logger (a+1, ["added one"]) logMultiplyTwo :: (Num a) => a -> Logger a logMultiplyTwo = Logger (a*2, ["Multiplied by two"]) --Define logOps logOps :: (Num a) => Logger a -> Logger a logOps lg = do v <- lg p1 <- logPlusOne v m2 <- logMultiplyTwo p1 return m2 -- Define a record function to record things in the log record :: String -> Logger() record s = Logger ((), [s])