-- Some sample functions inc :: Int -> Int inc x = x + 1 dec :: Int -> Int dec x = x - 1 double :: Int -> Int double x = 2 * x makeList :: Int -> [Int] makeList x = replicate x 0 -- Stringing the functions to make a sample computation computation = makeList . dec . double . dec . inc . double -- New type to track logging information newtype Logger a = Log(a, String) --Some logger helper functions getLog (Log(x, s)) = s getRes (Log(x, s)) = x -- Giving Functor definition to Logger instance Functor Logger where fmap f (Log(x, s)) = Log(f x, s) -- Defining my monad class as a functor with a return -- and join. fish will be used to compose embellished -- functions and can be derived from join. class Functor m => MyMonad m where ret :: a -> m a join :: m (m a) -> m a bind :: m a -> (a -> m b) -> m b bind ma f = join (fmap f ma) fish :: (b -> m c) -> (a -> m b) -> (a -> m c) fish g f = \x -> (let mb = f x in bind mb g) -- Giving monadic definition for Logger instance MyMonad Logger where ret x = Log(x, "") join (Log(Log(x, s2), s1)) = Log(x, s1 ++ "\n" ++ s2) -- Log(x, s1) >>= f = let Log(y, s2) = f x in -- Log(y, s1 ++ s2) --Make Logger a Haskell Monad instance Monad Logger where return = ret (>>=) = bind --Being a Haskell Monad requires Logger to be --an Applicative functor. --The definition below can make any monad an Applicative instance Applicative Logger where pure = return (<*>) mf ma = do f <- mf a <- ma return (f a) -- Embellished Logging functions incL :: Int -> Logger Int incL x = Log(x + 1, "Added 1") decL :: Int -> Logger Int decL x = Log(x - 1, "Decremented 1") doubleL :: Int -> Logger Int doubleL x = Log(2 * x, "Doubled") makeListL :: Int -> Logger [Int] makeListL x = Log(replicate x 0, "Made a list") -- Stringing the functions together with do notation computationL a = do b <- doubleL a c <- incL b d <- decL c e <- doubleL d f <- decL e makeListL f --Maybe helper functions getMaybe (Just x) = show x getMaybe Nothing = "There was nothing here" --Default Maybe functions for functions that can't fail incM :: Int -> Maybe Int incM x = return (inc x) decM :: Int -> Maybe Int decM x = return (dec x) doubleM :: Int -> Maybe Int doubleM x = return (double x) --Maybe function makeListM :: Int -> Maybe [Int] makeListM x = if x<=0 then Nothing else Just(replicate x 0) -- Stringing the functions together with do block computationM a = do b <- doubleM a c <- incM b d <- decM c e <- doubleM d f <- decM e makeListM f main = do putStrLn $ (show (computation 3)) putStrLn $ (show (getRes (computationL 3))) putStrLn $ (getLog (computationL 3)) putStrLn $ (getMaybe (computationM 3)) putStrLn $ (getMaybe (computationM 0))