newbie: Monad, equivalent notation using Control.Monad.guard

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" 2. Related issue: how can create a List monad so that I can input "l" argument of "test l" directly? TIA, Hugo F.

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 >> ... 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.
2. Related issue: how can create a List monad so that I can input "l" argument of "test l" directly?
I don't understand this question. Can you give an example of what you are trying to do? -Brent

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) Hmmm.. going to lookup more info on this.
2. Related issue: how can create a List monad so that I can input "l" argument of "test l" directly?
I don't understand this question. Can you give an example of what you are trying to do?
Weird. I was trying to execute: test1' [[1,2,3],[2,3],[3]] in a version that does not use Data.List.tails but could not. Now it works. Must have done something wrong. Hugo F.
-Brent
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

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. -Brent

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@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (2)
-
Brent Yorgey
-
Hugo Ferreira