# Question about example in 'using do notation with Writer' section of LYH

7 messages
Open this post in threaded view
|
Report Content as Inappropriate

## Question about example in 'using do notation with Writer' section of LYH

 Hello List, Chapter 14 of LYH ( http://learnyouahaskell.com/for-a-few-monads-more#reader ) has the following bit of code: 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 have a fair grasp of what's going bu the last line return(a*b) eludes me. Specifically its the a*b part that baffles me. I think 3 is bound to 'a' and 5 to 'b', then return(a*b) would put the value 15 in a context ... So what becomes of the string parts of the Writer monads created by logNumber 3 and logNumber 5 respectively. Regards, - Olumide _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Open this post in threaded view
|
Report Content as Inappropriate

## Re: Question about example in 'using do notation with Writer' section of LYH

 Nothing happens to them.  They are still in there.  Whereas logNumber always returns the number you give it, multiWithLog always returns 15 and appends two strings into its state ("got number 3 and 5"). You can return whatever value you want from a Monad.  In this case he's doing a * b, but you could do 2 * b, Just (a + b) or anything else.  As an example, here I return a tuple instead. multWithLogTuple :: Writer [String] (Int,Int,Int) multWithLogTuple = do     a <- logNumber 3     b <- logNumber 5     return (a,b,2*b) >runWriter multWithLogTuple ((3,5,10),["Got number: 3","Got number: 5"]) On Thu, Jan 26, 2017 at 10:41 AM, Olumide <[hidden email]> wrote: > Hello List, > > Chapter 14 of LYH ( http://learnyouahaskell.com/for-a-few-monads-more#reader> ) has the following bit of code: > > > 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 have a fair grasp of what's going bu the last line return(a*b) eludes me. > Specifically its the a*b part that baffles me. I think 3 is bound to 'a' and > 5 to 'b', then return(a*b) would put the value 15 in a context ... So what > becomes of the string parts of the Writer monads created by logNumber 3 and > logNumber 5 respectively. > > Regards, > > - Olumide > _______________________________________________ > Beginners mailing list > [hidden email] > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners_______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Open this post in threaded view
|
Report Content as Inappropriate

## Re: Question about example in 'using do notation with Writer' section of LYH

 In reply to this post by Olumide > what becomes of the string parts of the Writer monadsmultWithLog keeps [String] and outputs Intto fully benefit from Writer [String] Int, you'd call e.g. runWriter or execWritersimilar to other State state out monads, m state out lets you get/set/keep state as needed without passing it as an arg. state is there if you need it. _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Open this post in threaded view
|
Report Content as Inappropriate

## Re: Question about example in 'using do notation with Writer' section of LYH

 In reply to this post by David McBride On 26/01/2017 16:02, David McBride wrote: > Nothing happens to them.  They are still in there.  Whereas logNumber > always returns the number you give it, multiWithLog always returns 15 > and appends two strings into its state ("got number 3 and 5"). > > You can return whatever value you want from a Monad.  In this case > he's doing a * b, but you could do 2 * b, Just (a + b) or anything > else.  As an example, here I return a tuple instead. > > multWithLogTuple :: Writer [String] (Int,Int,Int) > multWithLogTuple = do >     a <- logNumber 3 >     b <- logNumber 5 >     return (a,b,2*b) > So return (a*b) still creates Writer [String] Int? I thought the [String] parts of 'a' and 'b' ought to be in the result but I see it needn't. - Olumide _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Open this post in threaded view
|
Report Content as Inappropriate

## Re: Question about example in 'using do notation with Writer' section of LYH

 In reply to this post by David McBride On 26/01/17 16:02, David McBride wrote: >> runWriter multWithLogTuple > ((3,5,10),["Got number: 3","Got number: 5"]) On second thoughts I don't think I understand how the logs are concatenated. I was expecting (15,["Got number: 15") in the original example. - Olumide _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Open this post in threaded view
|
Report Content as Inappropriate

## Re: Question about example in 'using do notation with Writer' section of LYH

 Fully expanding your program might help. One of the great things about Haskell is equational reasoning: if two things have been declared equal, you can substitute one for the other.First, let's desugar that do notation to the equivalent bind chain:multWithLog =  logNumber 3 >>= \a ->    logNumber 5 >>= \b ->      return (a*b)Evaluate the logNumber and return calls to normal form from their definitions, also considering the monoid definitions of (++) and mempty for lists:multWithLog =  Writer (3, ["Got number: 3"]) >>= \a ->    Writer (5, ["Got number: 5"]) >>= \b ->      Writer (a*b, [])Now, refer to the definition of (>>=) for Writer (as shown in LYAH):(Writer (x, v)) >>= f = let (Writer (y, v')) = f x in Writer (y, v `mappend` v')Rewritten as a lamba (and replacing `mappend` with (++) for brevity), this becomes:\(Writer (x, v)) f -> let (Writer (y, v')) = f x in Writer (y, v++v')It's no longer an infix function, so we'll have to shift things around a little. Here's what it expands to:multWithLog =  (\(Writer (x, v)) f ->                -- \      let (Writer (y, v')) = f x        -- | bind      in Writer (y, v++v'))             -- /    (Writer (3, ["Got number: 3"]))     -- Writer (x, v)    (\a ->                              -- f        (\(Writer (x2, v2)) f2 ->       -- \        let (Writer (y2, v2')) = f2 x2  -- | bind        in Writer (y2, v2++v2'))        -- /      (Writer (5, ["Got number: 5"]))   -- Writer (x2, v2)      (\b -> Writer (a*b, []))          -- f2    )                                   -- (end f)Now it's just a matter of simplification. Let's start by eliminating the first argument of each bind, i.e. (Writer (x,v)), by substituting with concrete values.multWithLog =  (\f ->                                        -- \ partially      let (Writer (y, v')) = f 3                -- | applied      in Writer (y, ["Got number: 3"]++v'))     -- / bind    (\a ->                                      -- f        (\f2 ->                                 -- \ partially        let (Writer (y2, v2')) = f2 5           -- | applied        in Writer (y2, ["Got number: 5"]++v2')) -- / bind      (\b -> Writer (a*b, []))                  -- f2    )                                           -- (end f)Substitute f2, and eliminate both \f2 and \b in the same way:multWithLog =  (\f ->      let (Writer (y, v')) = f 3      in Writer (y, ["Got number: 3"]++v'))    (\a ->      let (Writer (y2, v2')) = Writer (a*5, [])  -- applied f2      in Writer (y2, ["Got number: 5"]++v2')    )With a full match on the inner let block, that can also be eliminated:multWithLog =  (\f ->      let (Writer (y, v')) = f 3      in Writer (y, ["Got number: 3"]++v'))    (\a -> Writer (a*5, ["Got number: 5"]++[]))I'll forego the last few substitutions. If it's still not clear how you get to the final output, you should run through them yourself. You'll eventually reach a static definition of the result -- which shouldn't really be surprising, since there were no arguments to this "function" and its type doesn't contain -> anywhere. :)On Thu, Jan 26, 2017 at 1:34 PM, Olumide wrote:On 26/01/17 16:02, David McBride wrote: runWriter multWithLogTuple ((3,5,10),["Got number: 3","Got number: 5"]) On second thoughts I don't think I understand how the logs are concatenated. I was expecting (15,["Got number: 15") in the original example. - Olumide _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners