Quantcast

Need help understanding the tell function in the Monad Writer example in LYAH

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Need help understanding the tell function in the Monad Writer example in LYAH

Olumide
Hello List,

Would someone kindly explain how the tell function interacts with the
Writer Monad as show below:
(Example taken from chapter 14 of LYAH
http://learnyouahaskell.com/for-a-few-monads-more#reader )

multWithLog :: Writer [String] Int
multWithLog = do
        a <- logNumber 3
        b <- logNumber 5
        tell ["Gonna multiply these two"]
        return (a*b)

Result:
     ghci> runWriter multWithLog
     (15,["Got number: 3","Got number: 5","Gonna multiply these two"])

I know that tell function binds to an argument that is discarded but I
don't know how its argument "Gonna multiply these two" is concatenated
with the other the Writer created by logNumber 3 and logNumber 5.

Also, I don't understand the paragraph following the example:

"It's important that return (a*b) is the last line, because the result
of the last line in a do expression is the result of the whole do
expression. Had we put tell as the last line, () would have been the
result of this do expression. We'd lose the result of the
multiplication. However, the log would be the same."


Regards,

- Olumide
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Need help understanding the tell function in the Monad Writer example in LYAH

Francesco Ariis
On Fri, Feb 03, 2017 at 11:31:32AM +0000, Olumide wrote:

> Hello List,
>
> Would someone kindly explain how the tell function interacts with the Writer
> Monad as show below:
> (Example taken from chapter 14 of LYAH
> http://learnyouahaskell.com/for-a-few-monads-more#reader )
>
> multWithLog :: Writer [String] Int
> multWithLog = do
> a <- logNumber 3
> b <- logNumber 5
> tell ["Gonna multiply these two"]
> return (a*b)
>
> Result:
>     ghci> runWriter multWithLog
>     (15,["Got number: 3","Got number: 5","Gonna multiply these two"])
>
> I know that tell function binds to an argument that is discarded but I don't
> know how its argument "Gonna multiply these two" is concatenated with the
> other the Writer created by logNumber 3 and logNumber 5.
>
> Also, I don't understand the paragraph following the example:
>
> "It's important that return (a*b) is the last line, because the result of
> the last line in a do expression is the result of the whole do expression.
> Had we put tell as the last line, () would have been the result of this do
> expression. We'd lose the result of the multiplication. However, the log
> would be the same."
>
>
> Regards,
>
> - Olumide

Hello Olumide,
    a Writer do block can be read as a series of function which all have
a "hidden parameter". This parameter is the pile of log messages.
So you could as well substitute `tell ...` with

    myTell :: String -> Writer [String] ()
    myTell s = writer ((), [s])

and then in the do block

    -- ... receiving a list of log messages
    c <- myTell "something" -- adding mine to the list (and binding
                            -- a variable)
    return (a*b) -- c is not being used!
                 -- but the log message *is* there

You can verify this yourself by adding `logNumber` statement in a do
block and not using them in the last return statement. There too log
will appear even if the bound variable is unused.

    multWithLog :: Writer [String] Int
    multWithLog = do
     a <- logNumber 3
            b <- logNumber 5 -- not used but logged
        -- equivalent to: logNumber 5 (without b <-)
     return (a)

> Also, I don't understand the paragraph following the example:
>
> "It's important that return (a*b) is the last line, because the result of
> the last line in a do expression is the result of the whole do expression.
> Had we put tell as the last line, () would have been the result of this do
> expression. We'd lose the result of the multiplication. However, the log
> would be the same."

`tell` is really not much different from `myTell`. Let's examine it again:

    myTell :: String -> Writer [String] ()
    myTell s = writer ((), [s])

See the ()? It means it is *actually* returning something, a ().
Remember that `return` isn't the same `return` as in some imperative
languages: it only wraps a value in the monad we are using:

    return 5
    -- takes `5` and 'lifts' so it is usable inside the Writer
    -- monad: `(5, [])`

Putting a `tell "something"` after a return statement would overwrite
that result (and gives us back a () instead).

Did this help?
My tip for really getting a Monad in your brain is to reimplement it.
It is a very useful exercise.
Also learning *not* to use the `do notation` helps too, as having
operators instead of magic makes things easier to understand.

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Need help understanding the tell function in the Monad Writer example in LYAH

Olumide
I think I get it now. tell() is defined in Control.Monad.Writer as:

     tell   :: w -> m ()
     tell w = writer ((),w)

*also* the result if the do notation is the last expression; and that's
why the result of the computation will be lost (or disregarded) if
tell() comes last.

- Olumide

On 03/02/2017 13:54, Francesco Ariis wrote:

>     a Writer do block can be read as a series of function which all have
> a "hidden parameter". This parameter is the pile of log messages.
> So you could as well substitute `tell ...` with
>
>     myTell :: String -> Writer [String] ()
>     myTell s = writer ((), [s])
>
> and then in the do block
>
>     -- ... receiving a list of log messages
>     c <- myTell "something" -- adding mine to the list (and binding
>                             -- a variable)
>     return (a*b) -- c is not being used!
>                  -- but the log message *is* there
>
> You can verify this yourself by adding `logNumber` statement in a do
> block and not using them in the last return statement. There too log
> will appear even if the bound variable is unused.
>
>     multWithLog :: Writer [String] Int
>     multWithLog = do
>      a <- logNumber 3
>    b <- logNumber 5 -- not used but logged
>         -- equivalent to: logNumber 5 (without b <-)
>      return (a)
>
>> Also, I don't understand the paragraph following the example:
>>
>> "It's important that return (a*b) is the last line, because the result of
>> the last line in a do expression is the result of the whole do expression.
>> Had we put tell as the last line, () would have been the result of this do
>> expression. We'd lose the result of the multiplication. However, the log
>> would be the same."
>
> `tell` is really not much different from `myTell`. Let's examine it again:
>
>     myTell :: String -> Writer [String] ()
>     myTell s = writer ((), [s])
>
> See the ()? It means it is *actually* returning something, a ().
> Remember that `return` isn't the same `return` as in some imperative
> languages: it only wraps a value in the monad we are using:
>
>     return 5
>     -- takes `5` and 'lifts' so it is usable inside the Writer
>     -- monad: `(5, [])`
>
> Putting a `tell "something"` after a return statement would overwrite
> that result (and gives us back a () instead).
>
> Did this help?
> My tip for really getting a Monad in your brain is to reimplement it.
> It is a very useful exercise.
> Also learning *not* to use the `do notation` helps too, as having
> operators instead of magic makes things easier to understand.
>
> _______________________________________________
> 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
Loading...