Send Beginners mailing list submissions to beginners@haskell.org To subscribe or unsubscribe via the World Wide Web, visit http://www.haskell.org/mailman/listinfo/beginners or, via email, send a message with subject or body 'help' to beginners-requ...@haskell.org
You can reach the person managing the list at beginners-ow...@haskell.org When replying, please edit your Subject line so it is more specific than "Re: Contents of Beginners digest..." Today's Topics: 1. Re: newbie: Monad, equivalent notation using Control.Monad.guard (Brent Yorgey) 2. Re: recursion and pattern matching (Brent Yorgey) 3. Re: newbie: Monad, equivalent notation using Control.Monad.guard (Hugo Ferreira) 4. Weird (++) behavior when adding 2 vectors (Alexander Raasch) 5. Re: Weird (++) behavior when adding 2 vectors (Vlad Hanciuta) 6. Re: Weird (++) behavior when adding 2 vectors (Lorenzo Bolla) 7. Re: Weird (++) behavior when adding 2 vectors (Amy de Buitl?ir) 8. Re: Weird (++) behavior when adding 2 vectors (Alexander Raasch) ---------------------------------------------------------------------- Message: 1 Date: Tue, 18 Oct 2011 06:52:01 -0400 From: Brent Yorgey <byor...@seas.upenn.edu> Subject: Re: [Haskell-beginners] newbie: Monad, equivalent notation using Control.Monad.guard To: beginners@haskell.org Message-ID: <20111018105201.ga1...@seas.upenn.edu> Content-Type: text/plain; charset=us-ascii 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 ------------------------------ Message: 2 Date: Tue, 18 Oct 2011 07:04:35 -0400 From: Brent Yorgey <byor...@seas.upenn.edu> Subject: Re: [Haskell-beginners] recursion and pattern matching To: beginners@haskell.org Message-ID: <20111018110435.gb1...@seas.upenn.edu> Content-Type: text/plain; charset=iso-8859-1 On Tue, Oct 18, 2011 at 01:34:14AM -0700, Alia wrote: > I have a question about what's the idiomatic way to walk a tree where there > is also a requirement > for pattern-matching to draw variables out of the Node 'container': > > > > <Test.hs> > > module Test > > where > > data Tree a b = EmptyTree | Node a b [Tree a b] > ??????????? deriving (Show, Read, Eq)? > ? > t =? Node "goal" 1.0 [ > ??????? Node "c1" 0.5 [ > ??????????? Node "c3" 3.0 [ > ??????????????? Node "c5" 1.0 [] > ??????????????? ] > ??????????? ], > ??????? Node "c2" 0.5 [ > ??????????? Node "c4" 2.0 [] > ??????????? ] > ???? ] > > > sumTree :: (Num b) => Tree a b -> b > sumTree EmptyTree = 0 > sumTree (Node _ value []) = value > sumTree (Node _ value [x]) = value + sumTree x > sumTree (Node name value (x:xs)) = value + sumTree x + sumTree (Node name 0 > xs) > > depth :: Tree a b -> Int > depth EmptyTree = 0 > depth (Node _ _ []) = 1 > depth (Node _ _ [x]) = 1 + depth x > depth (Node n v (x:xs)) = 1 + depth (Node n v xs)? > > </Test.hs> > > Interactively: > > *Test> sumTree t > 8.0 > *Test> depth t > 4 > *Test> > > > This seems to work, but I have a sense that one should use folds and fmap and > that there > is a better and cleaner what to do this. Your sense is absolutely right! =) You are not taking advantage of the fact that [] is a functor and can be folded over, etc. -- you have essentially hardcoded a list fold into your sumTree and depth functions. First let's rewrite sumTree. We use 'map' to call 'sumTree' recursively on all the child trees, then sum the results: sumTree :: (Num b) => Tree a b -> b sumTree EmptyTree = 0 sumTree (Node _ value children) = value + sum (map sumTree children) Tada! We handled all those list cases (empty, single element, or cons) at once, in a general way. By the way, your implementation of 'depth' seems to be wrong: it only cares about the depth of the last child. I would think the idea would be to take the maximum depth of all the children and add one to that. I leave the rest for you: (1) rewrite depth in a similar way to sumTree, being sure to find the maximum depth of all the children (2) generalize both sumTree and depth to a treeFold function: treeFold :: c -> (a -> b -> [c] -> c) -> Tree a b -> c The first argument says what to do with EmptyTree, and the second argument says what to do with a Node. Once you have implemented treeFold you should be able to implement both sumTree and depth in terms of treeFold. Hope this helps. Let us know if you get stuck or have more questions! -Brent ------------------------------ Message: 3 Date: Tue, 18 Oct 2011 13:07:57 +0100 From: Hugo Ferreira <h...@inescporto.pt> Subject: Re: [Haskell-beginners] newbie: Monad, equivalent notation using Control.Monad.guard To: Brent Yorgey <byor...@seas.upenn.edu> Cc: beginners@haskell.org Message-ID: <4e9d6c1d.7020...@inescporto.pt> Content-Type: text/plain; charset=ISO-8859-1; format=flowed 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 > ------------------------------ Message: 4 Date: Tue, 18 Oct 2011 14:19:49 +0200 From: Alexander Raasch <i...@alexraasch.de> Subject: [Haskell-beginners] Weird (++) behavior when adding 2 vectors To: beginners@haskell.org Message-ID: <4e9d6ee5.6090...@alexraasch.de> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Hi, so I wrote this function to add two vectors represented as lists: add a b = add' a b [] where add' [] [] s = s add' (a:as) (b:bs) s ++ [a+b] OK, I tried this in ghci: > add [1,2,3] [1,2,3] [6,4,2] Hm, I expected the result to be [2,4,6], of course, since the currently added components always go to the end of the resulting vector. I then changed the last term in add' to [a+b] ++ s , but still > add [1,2,3] [1,2,3] [6,4,2] Can anyone explain this behavior to me. I think there should be some change in the result, no? Alex ------------------------------ Message: 5 Date: Tue, 18 Oct 2011 14:36:40 +0200 From: Vlad Hanciuta <wla...@gmail.com> Subject: Re: [Haskell-beginners] Weird (++) behavior when adding 2 vectors To: Alexander Raasch <i...@alexraasch.de> Cc: beginners@haskell.org Message-ID: <7c0687b5-7061-41e4-900c-fa0f1301b...@gmail.com> Content-Type: text/plain; charset=us-ascii Hi, Your code is not valid syntactically, I guess the last equation for add' is "add' (a:as) (b:bs) s = add' as bs s ++ [a+b]". In that case, the function application binds stronger that ++ operator so the expression is actually equivalent to "(add' as bs s) ++ [a+b]". So you can easily see that the list is computed backwards. Vlad On 18 Oct 2011, at 14:19, Alexander Raasch wrote: > Hi, > > so I wrote this function to add two vectors represented as lists: > > add a b = add' a b [] where > add' [] [] s = s > add' (a:as) (b:bs) s ++ [a+b] > > OK, I tried this in ghci: > > > add [1,2,3] [1,2,3] > [6,4,2] > > Hm, I expected the result to be [2,4,6], of course, since the currently added > components always go to the end of the resulting vector. I then changed the > last term in add' to > > [a+b] ++ s , > > but still > > > add [1,2,3] [1,2,3] > [6,4,2] > > Can anyone explain this behavior to me. I think there should be some change > in the result, no? > > Alex > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners ------------------------------ Message: 6 Date: Tue, 18 Oct 2011 13:48:40 +0100 From: Lorenzo Bolla <lbo...@gmail.com> Subject: Re: [Haskell-beginners] Weird (++) behavior when adding 2 vectors To: Alexander Raasch <i...@alexraasch.de> Cc: beginners@haskell.org Message-ID: <cadjgtrztafiymwfund8uyymw7djxvf-7snespn8w5hksm7m...@mail.gmail.com> Content-Type: text/plain; charset="utf-8" Hi, On Tue, Oct 18, 2011 at 1:19 PM, Alexander Raasch <i...@alexraasch.de>wrote: > Hi, > > so I wrote this function to add two vectors represented as lists: > > add a b = add' a b [] where > add' [] [] s = s > add' (a:as) (b:bs) s ++ [a+b] > > I think something mangled your function, as this is not valid Haskell code. Anyway, I tried to rewrite your function. The first version works as expected; the second gives reversed output. Note that there is no need for the accumulator "s". add a b = add' a b where add' [] [] = [] add' (a:as) (b:bs) = [a+b] ++ (add' as bs) add a b = add' a b where add' [] [] = [] add' (a:as) (b:bs) = (add' as bs) ++ [a+b] -- reversed output Obviously, the same function can be written as: zipWith (+) [1,2,3] [1,2,3] hth, L. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://www.haskell.org/pipermail/beginners/attachments/20111018/159bbe5b/attachment-0001.htm> ------------------------------ Message: 7 Date: Tue, 18 Oct 2011 12:51:27 +0000 (UTC) From: Amy de Buitl?ir <a...@nualeargais.ie> Subject: Re: [Haskell-beginners] Weird (++) behavior when adding 2 vectors To: beginners@haskell.org Message-ID: <loom.20111018t144110-...@post.gmane.org> Content-Type: text/plain; charset=us-ascii There seems to be something missing from this line: > add' (a:as) (b:bs) s ++ [a+b] Assuming you want to write your own function as an exercise, you could write it as a recursive function like this: add [] b = b add a [] = a add (a:as) (b:bs) = (a+b) : (add as bs) FYI, the easiest way to accomplish what you want is: add = zipWith (+) which is equivalent to: add a b = zipWith (+) a b Hope that helps ------------------------------ Message: 8 Date: Tue, 18 Oct 2011 15:04:25 +0200 From: Alexander Raasch <i...@alexraasch.de> Subject: Re: [Haskell-beginners] Weird (++) behavior when adding 2 vectors To: beginners@haskell.org Message-ID: <4e9d7959.7090...@alexraasch.de> Content-Type: text/plain; charset="utf-8"; Format="flowed" Hi, thanks for your answers. I'm exercising with different programming techniques, so the use of an accumulator was intentional although not necessary. As Vlad said, my mistake was the stronger binding of the function application. Sigh, ... Thank you all again. Alex On 10/18/2011 02:48 PM, Lorenzo Bolla wrote: > Hi, > > On Tue, Oct 18, 2011 at 1:19 PM, Alexander Raasch <i...@alexraasch.de > <mailto:i...@alexraasch.de>> wrote: > > Hi, > > so I wrote this function to add two vectors represented as lists: > > add a b = add' a b [] where > add' [] [] s = s > add' (a:as) (b:bs) s ++ [a+b] > > > I think something mangled your function, as this is not valid Haskell > code. > > Anyway, I tried to rewrite your function. > The first version works as expected; the second gives reversed output. > Note that there is no need for the accumulator "s". > > add a b = add' a b > where add' [] [] = [] > add' (a:as) (b:bs) = [a+b] ++ (add' as bs) > > add a b = add' a b > where add' [] [] = [] > add' (a:as) (b:bs) = (add' as bs) ++ [a+b] -- reversed > output > > Obviously, the same function can be written as: > zipWith (+) [1,2,3] [1,2,3] > > hth, > L. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://www.haskell.org/pipermail/beginners/attachments/20111018/a500e224/attachment.htm> ------------------------------ _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners End of Beginners Digest, Vol 40, Issue 27 *****************************************