[Haskell-beginners] newbie: Monad, equivalent notation using Control.Monad.guard

Hugo Ferreira hmf at inescporto.pt
Tue Oct 18 14:07:57 CEST 2011


On 10/18/2011 11:52 AM, Brent Yorgey wrote:
> On Tue, Oct 18, 2011 at 10:52:57AM +0100, Hugo Ferreira wrote:
>> Hello,
>>
>> On 10/17/2011 05:22 PM, Brent Yorgey wrote:
>>> On Mon, Oct 17, 2011 at 04:18:05PM +0100, Hugo Ferreira wrote:
>>>> Hello,
>>>>
>>>> I came across the following code:
>>>>
>>>> ngrams'' :: Int ->   [a] ->   [[a]]
>>>> ngrams'' n l = do
>>>>    t<- Data.List.tails l
>>>>    l<- [take n t]
>>>>    Control.Monad.guard (length l == n)
>>>>    return l
>>>>
>>>> and tried to use the ">>=" operator in order
>>>> to figure out how Monads work. I came up with:
>>>>
>>>> test l =
>>>>     (Data.List.tails l)
>>>>     >>= (\t ->   [take 2 t])
>>>>     >>= (\l ->   if (length l == 2) then [l] else [])
>>>>
>>>> Questions:
>>>> 1. How can I use Control.Monad.guard directly in "test l"
>>>
>>> test l =
>>>      (Data.List.tails l)
>>>      >>= \t ->   [take 2 t]
>>>      >>= \l ->   Control.Monad.guard (length l == 2)
>>>      >>    return l
>>>
>>> The rule is that
>>>
>>>    x<- foo
>>>
>>> desugars to
>>>
>>>    foo>>= \x ->   ...
>>>
>>> and
>>>
>>>    blah
>>>
>>> desugars to
>>>
>>>    blah>>   ...
>>>
>>
>> Ok, I was not aware of the>>.
>>
>>> One thing that might have been tripping you up is your extra
>>> parentheses around the lambda expressions.  If you have
>>>
>>>    >>= (\l ->   ...)
>>>    >>    foo...
>>>
>>> the l does not scope over foo... so you cannot mention it.  Instead
>>> what you want is
>>>
>>>    >>= \l ->   ...
>>>    >>    foo...
>>>
>>> so the lambda expression is actually   \l ->   ...>>   foo..., that is,
>>> it includes *everything* after the \l ->   ... and not just the stuff on
>>> that line.
>>>
>>
>> Hmmm. Still cannot wrap my mind around this B-(.
>>
>> [[1],[2],[3]]>>= \l ->  func1 l>>= \m ->  func2 m
>>
>> \l will hold each of the 3 elements of initial list
>>     these are concatenated with the results of func1
>>     results in a new list
>>
>> \m will have each element in the new list
>>     these are concatenated with the results of func2
>>     results in a last list
>>
>> is equal to ?
>>
>> (([[1],[2],[3]]>>= \l ->  func1 l)>>= \m ->  func2 m)
>
> Yes, your description is correct, and yes, these are equal. (Although
> the first is often more efficient.)  They are required to be equal by
> the monad laws. However, consider
>
>    [[1],[2],[3]]>>= \l ->  func1 l>>= \m ->  func2 m l
>
> and
>
>    (([[1],[2],[3]]>>= \l ->  func1 l)>>= \m ->  func2 m l)
>
> Notice that func2 now takes a second argument.  There is not even a
> question of whether these are equal: the second does not even compile,
> because the final 'l' is not in scope.  This is the point I was trying
> to make.

Aaaah. Got it.

Thanks,
Hugo F.

>
> -Brent
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>




More information about the Beginners mailing list