How to play with Control.Monad.Writer in haskell?

Viewed 15418

I'm new to functional programming and recently learning at Learn You a Haskell, but when I went through this chapter, I got stuck with the program below:

import Control.Monad.Writer  

logNumber :: Int -> Writer [String] Int  
logNumber x = Writer (x, ["Got number: " ++ show x])  

multWithLog :: Writer [String] Int  
multWithLog = do  
    a <- logNumber 3  
    b <- logNumber 5  
    return (a*b)

I saved these lines in a .hs file and but failed to import it into my ghci which complained:

more1.hs:4:15:
    Not in scope: data constructor `Writer'
    Perhaps you meant `WriterT' (imported from Control.Monad.Writer)
Failed, modules loaded: none.

I examined the type by ":info" command:

Prelude Control.Monad.Writer> :info Writer
type Writer w = WriterT w Data.Functor.Identity.Identity
               -- Defined in `Control.Monad.Trans.Writer.Lazy'

From my point of view, this was supposed to be something like "newtype Writer w a ..." so I'm confused about how to feed the data constructor and get a Writer.

I guess it might be a version-related problem and my ghci version is 7.4.1

3 Answers

I got a similar message from trying the LYAH "For a few Monads More" using the online Haskell editor in repl.it

I changed the import from:

import Control.Monad.Writer

to:

import qualified Control.Monad.Trans.Writer.Lazy as W

So my code now works looking like this (with inspiration from Kwang's Haskell Blog):

import Data.Monoid
import qualified Control.Monad.Trans.Writer.Lazy as W


output :: String -> W.Writer [String] ()
output x = W.tell [x]


gcd' :: Int -> Int -> W.Writer [String] Int  
gcd' a b  
    | b == 0 = do  
        output ("Finished with " ++ show a)
        return a  
    | otherwise = do  
        output (show a ++ " mod " ++ show b ++ " = " ++ show (a `mod` b))
        gcd' b (a `mod` b)

main :: IO()
main = mapM_ putStrLn $ snd $ W.runWriter (gcd' 8 3) 

Code is currently runable here

Related