From matthewjwilliams1 at googlemail.com Mon Feb 2 21:01:33 2009 From: matthewjwilliams1 at googlemail.com (Matthew J. Williams) Date: Mon Feb 2 20:51:44 2009 Subject: [Haskell-beginners] linked lists Message-ID: <4987a57e.1f07420a.4730.2db5@mx.google.com> Dear All What would be the haskell equivalent of the C++ linked list complete with nodes? the list structure -- x:[} -- is the closest I've found. Sincerely Matthew J. Williams From dpfrey at shaw.ca Mon Feb 2 21:15:27 2009 From: dpfrey at shaw.ca (David Frey) Date: Mon Feb 2 21:05:38 2009 Subject: [Haskell-beginners] linked lists In-Reply-To: <4987a57e.1f07420a.4730.2db5@mx.google.com> References: <4987a57e.1f07420a.4730.2db5@mx.google.com> Message-ID: <6f0b9611b74e935347ea6b59c82983b6@localhost> On Tue, 03 Feb 2009 02:01:33 +0000, "Matthew J. Williams" wrote: > Dear All > What would be the haskell equivalent of the C++ linked list complete > with nodes? the list structure -- x:[} -- is the closest I've found. > > Sincerely > Matthew J. Williams > There are certainly some similarities between std::list from C++ and Haskell's list, but there are also a lot of differences partly because C++ and Haskell are very different languages. What properties of lists are you interested in comparing? From matthewjwilliams1 at googlemail.com Mon Feb 2 21:45:32 2009 From: matthewjwilliams1 at googlemail.com (Matthew J. Williams) Date: Mon Feb 2 21:35:42 2009 Subject: [Haskell-beginners] Circular Linked Lists Message-ID: <4987afcd.130c420a.134e.4097@mx.google.com> Dear All How would one mimic, in Haskell, a C++ circular linked list i.e., where the last element precedes (points to) the first? Sincerely Matthew J. Williams From mle+cl at mega-nerd.com Mon Feb 2 21:53:17 2009 From: mle+cl at mega-nerd.com (Erik de Castro Lopo) Date: Mon Feb 2 21:43:36 2009 Subject: [Haskell-beginners] Circular Linked Lists In-Reply-To: <4987afcd.130c420a.134e.4097@mx.google.com> References: <4987afcd.130c420a.134e.4097@mx.google.com> Message-ID: <20090203135317.beaed216.mle+cl@mega-nerd.com> Matthew J. Williams wrote: > How would one mimic, in Haskell, a C++ circular linked list i.e., > where the last element precedes (points to) the first? Try this, "Tying the Knot": http://www.haskell.org/haskellwiki/Tying_the_Knot Erik -- -- ----------------------------------------------------------------- Erik de Castro Lopo ----------------------------------------------------------------- "I consider C++ the most significant technical hazard to the survival of your project and do so without apologies." -- Alistair Cockburn From RafaelGCPP.Linux at gmail.com Tue Feb 3 08:46:06 2009 From: RafaelGCPP.Linux at gmail.com (Rafael Gustavo da Cunha Pereira Pinto) Date: Tue Feb 3 08:36:13 2009 Subject: [Haskell-beginners] Circular Linked Lists In-Reply-To: <20090203135317.beaed216.mle+cl@mega-nerd.com> References: <4987afcd.130c420a.134e.4097@mx.google.com> <20090203135317.beaed216.mle+cl@mega-nerd.com> Message-ID: <351ff25e0902030546g774a251as22bf76805e2fdca5@mail.gmail.com> Matthew, I would strongly suggest taking a look on SPJ's presentation at OSCON 2007 (video at http://blip.tv/file/324976). He shows a very interesting circular list (with a zipper). Since you are interested in functional data structures, Chris Okasaki's book "Purely Functional Data Structures" is a great source too! On Tue, Feb 3, 2009 at 00:53, Erik de Castro Lopo > wrote: > Matthew J. Williams wrote: > > > How would one mimic, in Haskell, a C++ circular linked list i.e., > > where the last element precedes (points to) the first? > > Try this, "Tying the Knot": > > http://www.haskell.org/haskellwiki/Tying_the_Knot > > Erik > -- > -- > ----------------------------------------------------------------- > Erik de Castro Lopo > ----------------------------------------------------------------- > "I consider C++ the most significant technical hazard to the survival > of your project and do so without apologies." -- Alistair Cockburn > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -- Rafael Gustavo da Cunha Pereira Pinto Electronic Engineer, MSc. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090203/71a5c24d/attachment.htm From bayer at cpw.math.columbia.edu Tue Feb 3 08:56:34 2009 From: bayer at cpw.math.columbia.edu (Dave Bayer) Date: Tue Feb 3 08:46:43 2009 Subject: [Haskell-beginners] Circular Linked Lists In-Reply-To: <4987afcd.130c420a.134e.4097@mx.google.com> References: <4987afcd.130c420a.134e.4097@mx.google.com> Message-ID: <19BF564D-0337-48C3-8996-8AA923998DBE@math.columbia.edu> On Feb 2, 2009, at 9:45 PM, Matthew J. Williams wrote: > Dear All > How would one mimic, in Haskell, a C++ circular linked list i.e., > where the last element precedes (points to) the first? You are getting deep answers to what is perhaps a simple question. You haven't said exactly what you want to do with a circular linked list, and people are perhaps fearing the trickiest applications. Have you tried the Prelude function cycle? > cycle :: [a] -> [a] > cycle ties a finite list into a circular one, or equivalently, the > infinite repetition of the original list. It is the identity on > infinite lists. For instance, in ghci one gets > Prelude> [1..3] > [1,2,3] > Prelude> take 10 $ cycle [1..3] > [1,2,3,1,2,3,1,2,3,1] cycle doesn't actually construct in memory a cyclic data structure, as one might in C. It's more like those repeat bars in sheet music. From byorgey at seas.upenn.edu Tue Feb 3 09:17:12 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Tue Feb 3 09:07:20 2009 Subject: [Haskell-beginners] Circular Linked Lists In-Reply-To: <19BF564D-0337-48C3-8996-8AA923998DBE@math.columbia.edu> References: <4987afcd.130c420a.134e.4097@mx.google.com> <19BF564D-0337-48C3-8996-8AA923998DBE@math.columbia.edu> Message-ID: <20090203141712.GA24679@seas.upenn.edu> > > cycle doesn't actually construct in memory a cyclic data structure, as one > might in C. It's more like those repeat bars in sheet music. It doesn't? cycle xs = xs' where xs' = xs ++ xs' That sure looks like a cyclic data structure to me! xs' references a thunk which computes (xs ++ xs'); this thunk, in turn, references xs'. cycle is memory-efficient precisely because it *does* actually construct a cyclic data structure. -Brent From john.hartnup at gmail.com Tue Feb 3 09:52:33 2009 From: john.hartnup at gmail.com (John Hartnup) Date: Tue Feb 3 09:42:40 2009 Subject: [Haskell-beginners] Circular Linked Lists In-Reply-To: <20090203141712.GA24679@seas.upenn.edu> References: <4987afcd.130c420a.134e.4097@mx.google.com> <19BF564D-0337-48C3-8996-8AA923998DBE@math.columbia.edu> <20090203141712.GA24679@seas.upenn.edu> Message-ID: <6c1ba2fc0902030652r36860d5na77a32f21f9cb6d9@mail.gmail.com> 2009/2/3 Brent Yorgey : > > cycle xs = xs' where xs' = xs ++ xs' > > That sure looks like a cyclic data structure to me! xs' references a > thunk which computes (xs ++ xs'); this thunk, in turn, references > xs'. cycle is memory-efficient precisely because it *does* actually > construct a cyclic data structure. That's just magnificent! -- "There is no way to peace; peace is the way" From bayer at cpw.math.columbia.edu Tue Feb 3 09:54:46 2009 From: bayer at cpw.math.columbia.edu (Dave Bayer) Date: Tue Feb 3 09:44:53 2009 Subject: [Haskell-beginners] Circular Linked Lists In-Reply-To: <20090203141712.GA24679@seas.upenn.edu> References: <4987afcd.130c420a.134e.4097@mx.google.com> <19BF564D-0337-48C3-8996-8AA923998DBE@math.columbia.edu> <20090203141712.GA24679@seas.upenn.edu> Message-ID: So the "repeat bars" are there until the first pass through the list completes, otherwise cycle would be bottom on infinite lists. Thereafter, you're saying that a core dump would reveal a completely homogeneous memory representation, just like C code, that one could pass through the foreign function interface to C code? GHC seems to have a special awareness of cyclic lists. For example, ghci computes > (zip (cycle [1..3]) (cycle [1..4])) !! (1000^1000) immediately, as if it knows enough to compute 1000^1000 mod 12, by repeated squaring. On Feb 3, 2009, at 9:17 AM, Brent Yorgey wrote: > It doesn't? > > cycle xs = xs' where xs' = xs ++ xs' > > That sure looks like a cyclic data structure to me! xs' references a > thunk which computes (xs ++ xs'); this thunk, in turn, references > xs'. cycle is memory-efficient precisely because it *does* actually > construct a cyclic data structure. From daniel.is.fischer at web.de Tue Feb 3 10:04:11 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Tue Feb 3 09:51:43 2009 Subject: [Haskell-beginners] Circular Linked Lists In-Reply-To: References: <4987afcd.130c420a.134e.4097@mx.google.com> <20090203141712.GA24679@seas.upenn.edu> Message-ID: <200902031604.11954.daniel.is.fischer@web.de> Am Dienstag, 3. Februar 2009 15:54 schrieb Dave Bayer: > So the "repeat bars" are there until the first pass through the list > completes, otherwise cycle would be bottom on infinite lists. > Thereafter, you're saying that a core dump would reveal a completely > homogeneous memory representation, just like C code, that one could > pass through the foreign function interface to C code? > > GHC seems to have a special awareness of cyclic lists. For example, > ghci computes > > > (zip (cycle [1..3]) (cycle [1..4])) !! (1000^1000) No, it's that the type of (!!) is [a] -> Int -> a, and 1000^1000 :: Int is 0. > > immediately, as if it knows enough to compute 1000^1000 mod 12, by > repeated squaring. > > On Feb 3, 2009, at 9:17 AM, Brent Yorgey wrote: > > It doesn't? > > > > cycle xs = xs' where xs' = xs ++ xs' > > > > That sure looks like a cyclic data structure to me! xs' references a > > thunk which computes (xs ++ xs'); this thunk, in turn, references > > xs'. cycle is memory-efficient precisely because it *does* actually > > construct a cyclic data structure. > From byorgey at seas.upenn.edu Tue Feb 3 10:07:50 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Tue Feb 3 09:57:56 2009 Subject: [Haskell-beginners] Circular Linked Lists In-Reply-To: References: <4987afcd.130c420a.134e.4097@mx.google.com> <19BF564D-0337-48C3-8996-8AA923998DBE@math.columbia.edu> <20090203141712.GA24679@seas.upenn.edu> Message-ID: <20090203150750.GA25899@seas.upenn.edu> On Tue, Feb 03, 2009 at 09:54:46AM -0500, Dave Bayer wrote: > So the "repeat bars" are there until the first pass through the list > completes, otherwise cycle would be bottom on infinite lists. Thereafter, > you're saying that a core dump would reveal a completely homogeneous memory > representation, just like C code, that one could pass through the foreign > function interface to C code? I'm not really sure what you mean by "repeat bars". There really is a cyclic data structure in memory at all times--it's just that until the first pass through the list, part of it is a thunk. After a complete pass to the list, however, a core dump would indeed reveal something like what you suggest. > > GHC seems to have a special awareness of cyclic lists. For example, ghci > computes > >> (zip (cycle [1..3]) (cycle [1..4])) !! (1000^1000) > > immediately, as if it knows enough to compute 1000^1000 mod 12, by repeated > squaring. I came to the same conclusion as Daniel but it took me a few minutes of puzzlement. Besides, it should actually be equal to (2,1), not (1,1). =) -Brent From bayer at cpw.math.columbia.edu Tue Feb 3 10:15:10 2009 From: bayer at cpw.math.columbia.edu (Dave Bayer) Date: Tue Feb 3 10:05:17 2009 Subject: [Haskell-beginners] Circular Linked Lists In-Reply-To: <200902031604.11954.daniel.is.fischer@web.de> References: <4987afcd.130c420a.134e.4097@mx.google.com> <20090203141712.GA24679@seas.upenn.edu> <200902031604.11954.daniel.is.fischer@web.de> Message-ID: On Feb 3, 2009, at 10:04 AM, Daniel Fischer wrote: >> GHC seems to have a special awareness of cyclic lists. For example, >> ghci computes >> >>> (zip (cycle [1..3]) (cycle [1..4])) !! (1000^1000) > > No, it's that the type of (!!) is [a] -> Int -> a, and 1000^1000 :: > Int is 0. > >> >> immediately, as if it knows enough to compute 1000^1000 mod 12, by >> repeated squaring. Thanks. The following takes forever, but it doesn't consume memory: > Prelude> :m Data.List > Prelude Data.List> genericIndex (zip (cycle [1..3]) (cycle [1..4])) > (1000^1000) So zip is doing something smart here with cyclic lists. From bayer at cpw.math.columbia.edu Tue Feb 3 10:26:12 2009 From: bayer at cpw.math.columbia.edu (Dave Bayer) Date: Tue Feb 3 10:16:20 2009 Subject: [Haskell-beginners] Circular Linked Lists In-Reply-To: References: <4987afcd.130c420a.134e.4097@mx.google.com> <20090203141712.GA24679@seas.upenn.edu> <200902031604.11954.daniel.is.fischer@web.de> Message-ID: On Feb 3, 2009, at 10:15 AM, Dave Bayer wrote: > > The following takes forever, but it doesn't consume memory: > >> Prelude> :m Data.List >> Prelude Data.List> genericIndex (zip (cycle [1..3]) (cycle [1..4])) >> (1000^1000) > > So zip is doing something smart here with cyclic lists. No, I just wasn't saving the head. This burns memory: > Prelude Data.List> let a = zip (cycle [1..3]) (cycle [1..4]) > Prelude Data.List> head a > (1,1) > Prelude Data.List> genericIndex a (1000^1000) > : memory allocation failed (requested 2097152 bytes) From patrick.leboutillier at gmail.com Tue Feb 3 20:58:55 2009 From: patrick.leboutillier at gmail.com (Patrick LeBoutillier) Date: Tue Feb 3 20:49:02 2009 Subject: [Haskell-beginners] Parsing a file with data divided into sections Message-ID: Hi all, I wanted to parse a file that looks like this: MONDAY JOHN JIM LINDA TUESDAY BILL BOB WEDNESDAY THURSDAY SAM TODD LARRY LUKE FRIDAY TED in order to count the number of people for each day. After a (very) long time and a lot of trial and error, I managed to do it with this program: import Char (isSpace) main = interact (unlines . countSections . lines) where countSections = map (show) . snd . foldr compileSections (0, []) compileSections line (n, acc) = if isSection line then (0, (line, n) : acc) else (n + 1, acc) isSection line = not . isSpace . head $ line which outputs: ("MONDAY",3) ("TUESDAY",2) ("WEDNESDAY",0) ("THURSDAY",4) ("FRIDAY",1) I had quite a hard time figuring out how to keep count of the number of records in each sections. Is there a more obvious way to handle these types of problems? Are there some builtins that could of made it easier? In Perl I would probably have used a hash and a variable to keep count of the current day, incrementing the hash value for each person until I got to the next day, but it's not obvious to me how to transpose this technique to functional programming. Thanks a lot, Patrick -- ===================== Patrick LeBoutillier Rosem?re, Qu?bec, Canada From magnus at therning.org Wed Feb 4 05:02:30 2009 From: magnus at therning.org (Magnus Therning) Date: Wed Feb 4 04:52:37 2009 Subject: [Haskell-beginners] Parsing a file with data divided into sections In-Reply-To: References: Message-ID: On Wed, Feb 4, 2009 at 1:58 AM, Patrick LeBoutillier wrote: > Hi all, > > I wanted to parse a file that looks like this: > > MONDAY > JOHN > JIM > LINDA > TUESDAY > BILL > BOB > WEDNESDAY > THURSDAY > SAM > TODD > LARRY > LUKE > FRIDAY > TED > > in order to count the number of people for each day. After a (very) > long time and a lot of trial and > error, I managed to do it with this program: > > import Char (isSpace) > > main = interact (unlines . countSections . lines) > where countSections = map (show) . snd . foldr compileSections (0, []) > compileSections line (n, acc) = > if isSection line > then (0, (line, n) : acc) > else (n + 1, acc) > isSection line = not . isSpace . head $ line > > which outputs: > > ("MONDAY",3) > ("TUESDAY",2) > ("WEDNESDAY",0) > ("THURSDAY",4) > ("FRIDAY",1) > > I had quite a hard time figuring out how to keep count of the number > of records in each sections. > Is there a more obvious way to handle these types of problems? Are > there some builtins that could > of made it easier? I think that you've pretty much used accumulators in the way they most often are used. In many cases you don't _have_ to keep count though. Here's one way to get the same result, but without keeping count: countDays [] = [] countDays ls = let day = head ls count = length $ takeWhile (isSpace . head) $ tail ls in (day, count) : countDays (drop (1 + count) ls) main = interact (unlines . map show . countDays . lines) > In Perl I would probably have used a hash and a variable to keep count > of the current day, incrementing > the hash value for each person until I got to the next day, but it's > not obvious to me how to transpose this > technique to functional programming. Often transposing from imperative to functional isn't what you want to do. One of the arguments for learning both imperative and functional languages is that they approach problems differently, resulting in different solutions. I suspect you will find Haskell, and indeed any functional language, difficult to use if you try to "think imperative". It takes time to learn new ways to think about problems, but in the end you'll never look at things the same way again :-) /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus?therning?org Jabber: magnus?therning?org http://therning.org/magnus identi.ca|twitter: magthe From apfelmus at quantentunnel.de Wed Feb 4 06:10:02 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Wed Feb 4 05:59:34 2009 Subject: [Haskell-beginners] Re: Parsing a file with data divided into sections In-Reply-To: References: Message-ID: Magnus Therning wrote: > Patrick LeBoutillier wrote: >> >> I wanted to parse a file that looks like this: >> >> MONDAY >> JOHN >> JIM >> LINDA >> TUESDAY >> BILL >> BOB >> WEDNESDAY >> THURSDAY >> SAM >> TODD >> LARRY >> LUKE >> FRIDAY >> TED >> >> in order to count the number of people for each day. After a (very) >> long time and a lot of trial and error, >> I managed to do it with this program: Nice program, especially your use of function composition is good style. > I think that you've pretty much used accumulators in the way they most > often are used. In many cases you don't _have_ to keep count though. > Here's one way to get the same result, but without keeping count: > > countDays [] = [] > countDays ls = let > day = head ls > count = length $ takeWhile (isSpace . head) $ tail ls > in (day, count) : countDays (drop (1 + count) ls) > > main = interact (unlines . map show . countDays . lines) Here's a version using span from the Prelude: main = interact $ unlines . map show . countDays . lines countDays [] = [] countDays (day:xs) = (day, length people) : countDays xs' where (people, xs') = span (isSpace . head) xs Note that this file format is very simple and it's ok to use lines and isSpace to parse it. But the tool of choice are parser combinators like Text.Parsec or Text.ParserCombinators.ReadP . -- http://apfelmus.nfshost.com From magnus at therning.org Wed Feb 4 06:43:45 2009 From: magnus at therning.org (Magnus Therning) Date: Wed Feb 4 06:33:52 2009 Subject: [Haskell-beginners] Re: Parsing a file with data divided into sections In-Reply-To: References: Message-ID: On Wed, Feb 4, 2009 at 11:10 AM, Heinrich Apfelmus wrote: [..] > Here's a version using span from the Prelude: > > main = interact $ unlines . map show . countDays . lines > > countDays [] = [] > countDays (day:xs) = (day, length people) : countDays xs' > where (people, xs') = span (isSpace . head) xs Ah, yes, `span` is the function I was looking for! I would have found it if I had bothered to go to Hoogle :-( /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus?therning?org Jabber: magnus?therning?org http://therning.org/magnus identi.ca|twitter: magthe From patrick.leboutillier at gmail.com Wed Feb 4 09:15:03 2009 From: patrick.leboutillier at gmail.com (Patrick LeBoutillier) Date: Wed Feb 4 09:05:08 2009 Subject: [Haskell-beginners] Re: Parsing a file with data divided into sections In-Reply-To: References: Message-ID: > Nice program, especially your use of function composition is good style. Thanks, I must admit I put alot of time into refactoring it. There's so many different ways of doing stuff (and then simplifying them) in Haskell! >> I think that you've pretty much used accumulators in the way they most >> often are used. In many cases you don't _have_ to keep count though. >> Here's one way to get the same result, but without keeping count: >> >> countDays [] = [] >> countDays ls = let >> day = head ls >> count = length $ takeWhile (isSpace . head) $ tail ls >> in (day, count) : countDays (drop (1 + count) ls) >> >> main = interact (unlines . map show . countDays . lines) > > Here's a version using span from the Prelude: > > main = interact $ unlines . map show . countDays . lines > > countDays [] = [] > countDays (day:xs) = (day, length people) : countDays xs' > where (people, xs') = span (isSpace . head) xs > Both of these examples are great and exactly what I was looking for: a different approach to the problem. I guess the step that was missing in my "thought process" is that recursion doesn't have to imply processing the list elements 1 by 1 (1 recursive call for each element). Of course it makes perfect sense once you see it.... Thanks a lot to everyone, as usual the people on this list are always very kind and helpful. Patrick > > Note that this file format is very simple and it's ok to use lines and > isSpace to parse it. But the tool of choice are parser combinators > like Text.Parsec or Text.ParserCombinators.ReadP . > > > -- > http://apfelmus.nfshost.com > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -- ===================== Patrick LeBoutillier Rosem?re, Qu?bec, Canada From byorgey at seas.upenn.edu Wed Feb 4 09:49:27 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Wed Feb 4 09:39:31 2009 Subject: [Haskell-beginners] Re: Parsing a file with data divided into sections In-Reply-To: References: Message-ID: <20090204144927.GA20574@seas.upenn.edu> On Wed, Feb 04, 2009 at 12:10:02PM +0100, Heinrich Apfelmus wrote: > Magnus Therning wrote: > > Here's a version using span from the Prelude: > > main = interact $ unlines . map show . countDays . lines > > countDays [] = [] > countDays (day:xs) = (day, length people) : countDays xs' > where (people, xs') = span (isSpace . head) xs > > > Note that this file format is very simple and it's ok to use lines and > isSpace to parse it. But the tool of choice are parser combinators > like Text.Parsec or Text.ParserCombinators.ReadP . Let me also point out that using the 'split' package from Hackage [1], we can implement this nicely without any icky manual recursion, and without resorting to a full-blown parsing library: import Data.List.Split import Data.Char main = interact (unlines . map show . countDays . lines) countDays = map length . tail . splitWhen isDay where isDay = not . isSpace . head 'splitWhen' splits the list of lines into chunks using things that satisfy the predicate as delimiters; then we just 'map length' over those chunks to count the people for each day. The 'tail' is necessary because the split actually produces a blank list of people *before* the first day, but otherwise this is entirely straightforward. -Brent [1] http://hackage.haskell.org/cgi-bin/hackage-scripts/package/split From wagner.andrew at gmail.com Thu Feb 5 16:11:17 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Thu Feb 5 16:01:18 2009 Subject: [Haskell-beginners] Just how unsafe is unsafe Message-ID: So we all know the age-old rule of thumb, that unsafeXXX is simply evil and anybody that uses it should be shot (except when it's ok). I understand that unsafeXXX allows impurity, which defiles our ability to reason logically about haskell programs like we would like to. My question is, to what extent is this true? Suppose we had a module, UnsafeRandoms, which had a function that would allow you to generate a different random number every time you call it. The semantics are relatively well-defined, impurity is safely sectioned off in its own impure module, which is clearly labeled as such. How much damage does this do? Can we push the lines elsewhere? Is sectioning unsafeXXX into Unsafe modules a useful idiom that we can use for other things as well? -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090205/e24438ba/attachment.htm From bugfact at gmail.com Thu Feb 5 17:47:28 2009 From: bugfact at gmail.com (Peter Verswyvelen) Date: Thu Feb 5 17:37:29 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Just how unsafe is unsafe In-Reply-To: <498B68AE.70106@pikewerks.com> References: <498B5BF3.5060405@pikewerks.com> <498B68AE.70106@pikewerks.com> Message-ID: Well, one could say that a truly random number function takes as input time and some constant unique identifier (serial number) of the TRND device and gives you the random value measured at that time by this device. Of course this would mean the random value is not really random, since "the potential creator of the universe" would have known the value already, but to all humble beings living in the bubble, it would be Truly Random :) Then the question is, is time a function? If so, is it discrete? Okay, this is not Haskell anymore, this would become philosophy, and since a good and smart friend of mine told me that nobody really knows what time is, this is off topic. Sorry! :) On Thu, Feb 5, 2009 at 11:31 PM, Jake McArthur wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Peter Verswyvelen wrote: > | I do have asked myself the question whether a "really random generating" > | function could be regarded as "pure" somehow (actually would a true > | random function still be a mathematical function?) > | > | E.g. the function would return a true (not pseudo) random number, > | practically unpredictable (e.g. hardware assisted, using some physical > | phenomenon, e.g. using atmospheric noise or something). So you surely > | won't get referential transparency but since the function is really > | random, this would be correct behavior? > > An informal definition of a function might be something like a black box > that takes and input and produces an output, and for each possible > input, the output must be the same. Taking this to be a function, there > is really no such thing as a random function, and if there was, it > wouldn't even need to be a function. (What would the input to it be?) > > If you wanted to mathematically represent a random number, it would, in > most cases I can think of, best be represented as a free variable. In a > program, such a free variable could be filled in by the runtime. > Conveniently, (and by no coincidence) this is something the IO monad can > provide for us! :) > > | Of course you could just put this random generator in the IO monad, but > | certain algorithms- like Monte Carlo - intuitively don't seem to operate > | in a IO monad to me. > > Why not? > > A Random monad might be more appropriate in this case anyway. Such a > monad is a State monad that hold a random seed. Every time a random > number is needed, the seed is passed to a deterministic psuedo-random > number generator, and a new seed is put as the next state. > > If a truly random number is ever needed, either IO or unsafeInterleaveIO > will be needed. The use of unsafeInterleaveIO would be a (rightly) > controversial choice though. > > - - Jake > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.9 (GNU/Linux) > Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org > > iEYEARECAAYFAkmLaK4ACgkQye5hVyvIUKk88QCfRksu7z80QmzgjUvmiyrzDDjl > QnsAn1R5DHz2tJpWP3yb0+U+loyBdyCX > =RIX9 > -----END PGP SIGNATURE----- > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090205/c98379ee/attachment.htm From max.rabkin at gmail.com Thu Feb 5 17:22:45 2009 From: max.rabkin at gmail.com (Max Rabkin) Date: Thu Feb 5 21:28:57 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Just how unsafe is unsafe In-Reply-To: References: <498B5BF3.5060405@pikewerks.com> Message-ID: 2009/2/5 Peter Verswyvelen : > Of course you could just put this random generator in the IO monad, but > certain algorithms- like Monte Carlo - intuitively don't seem to operate in > a IO monad to me. For PRNGs, only State is needed, not IO. But you might find the `randoms' function useful: it returns in infinite list of pseudo-random values. --Max From jonathanccast at fastmail.fm Thu Feb 5 16:33:13 2009 From: jonathanccast at fastmail.fm (Jonathan Cast) Date: Thu Feb 5 21:29:22 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Just how unsafe is unsafe In-Reply-To: References: Message-ID: <1233869593.19682.61.camel@jcchost> On Thu, 2009-02-05 at 16:11 -0500, Andrew Wagner wrote: > So we all know the age-old rule of thumb, that unsafeXXX is simply > evil and anybody that uses it should be shot (except when it's ok). > I understand that unsafeXXX allows impurity, which defiles our ability > to reason logically about haskell programs like we would like to. Not just that! Parametric polymorphism is unsound in combination with mutable values; but unsafePerformIO turns on exactly that combination. unsafeCoerce :: alpha -> beta unsafeCoerce x = unsafePerformIO $ do let r = unsafePerformIO $ newIORef undefined r `writeIORef` x readIORef r > My question is, to what extent is this true? unsafePerformIO is a true function --- in the absence of any fancy compiler trickery --- on a small subset of its domain. Outside of that subset, I would regard use of unsafePerformIO simply as a bug --- violation of an unchecked precondition. Period. > Suppose we had a module, UnsafeRandoms, which had a function that > would allow you to generate a different random number every time you > call it. unsafePerformIO does not allow you to guarantee this! If I defined myRandomNumber = unsafePerformIO $ randomNumber then the compiler is permitted to call randomNumber (at most) *once*, and use that number throughout the program. > The semantics are relatively well-defined, Leaving aside the issue above, I would think complete randomness was nearly the worst possible case, semantically. (The *worst* worst possible case would be non-statistical non-determinism --- which is what you actually get here). > impurity is safely sectioned off in its own impure module, which is > clearly labeled as such. How much damage does this do? Well, it forces me to chase your libraries import lists to decide whether I want to trust your code, for one thing. Haskell is all about making it easier to audit code, not harder. > Can we push the lines elsewhere? I'd rather not. > Is sectioning unsafeXXX into Unsafe modules a useful idiom that we can > use for other things as well? I'd rather not write other unsafe functions at all. Sectioning off things that need to be unsafe into pure solutions --- like, say, monads --- is a much better idea. (Go read the global variables thread from last year). jcc From jake at pikewerks.com Thu Feb 5 16:36:51 2009 From: jake at pikewerks.com (Jake McArthur) Date: Thu Feb 5 21:29:55 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Just how unsafe is unsafe In-Reply-To: References: Message-ID: <498B5BF3.5060405@pikewerks.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Andrew Wagner wrote: | I understand that unsafeXXX allows impurity, which defiles our ability | to reason logically about haskell programs like we would like to. My | question is, to what extent is this true? My opinion is that unsafeXXX is acceptable only when its use is preserved behind an abstraction that is referentially transparent and type safe. Others may be able to help refine this statement. | Suppose we had a module, UnsafeRandoms, which had a function that would | allow you to generate a different random number every time you call it. | The semantics are relatively well-defined, impurity is safely sectioned | off in its own impure module, which is clearly labeled as such. How much | damage does this do? This does not preserve referential transparency, so by my criteria above this is an unacceptable use of an unsafe function. One reason it's a bad idea is that it removes determinism, which may be very important for testability. - - Jake -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkmLW/MACgkQye5hVyvIUKniOACfQGPLiY65+eiMfsv7BlbYLI++ Bd0An1N5wp6TDkJzhmdw831/Gj45Bv9S =TnQg -----END PGP SIGNATURE----- From jake at pikewerks.com Thu Feb 5 17:31:10 2009 From: jake at pikewerks.com (Jake McArthur) Date: Thu Feb 5 21:29:59 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Just how unsafe is unsafe In-Reply-To: References: <498B5BF3.5060405@pikewerks.com> Message-ID: <498B68AE.70106@pikewerks.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Peter Verswyvelen wrote: | I do have asked myself the question whether a "really random generating" | function could be regarded as "pure" somehow (actually would a true | random function still be a mathematical function?) | | E.g. the function would return a true (not pseudo) random number, | practically unpredictable (e.g. hardware assisted, using some physical | phenomenon, e.g. using atmospheric noise or something). So you surely | won't get referential transparency but since the function is really | random, this would be correct behavior? An informal definition of a function might be something like a black box that takes and input and produces an output, and for each possible input, the output must be the same. Taking this to be a function, there is really no such thing as a random function, and if there was, it wouldn't even need to be a function. (What would the input to it be?) If you wanted to mathematically represent a random number, it would, in most cases I can think of, best be represented as a free variable. In a program, such a free variable could be filled in by the runtime. Conveniently, (and by no coincidence) this is something the IO monad can provide for us! :) | Of course you could just put this random generator in the IO monad, but | certain algorithms- like Monte Carlo - intuitively don't seem to operate | in a IO monad to me. Why not? A Random monad might be more appropriate in this case anyway. Such a monad is a State monad that hold a random seed. Every time a random number is needed, the seed is passed to a deterministic psuedo-random number generator, and a new seed is put as the next state. If a truly random number is ever needed, either IO or unsafeInterleaveIO will be needed. The use of unsafeInterleaveIO would be a (rightly) controversial choice though. - - Jake -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkmLaK4ACgkQye5hVyvIUKk88QCfRksu7z80QmzgjUvmiyrzDDjl QnsAn1R5DHz2tJpWP3yb0+U+loyBdyCX =RIX9 -----END PGP SIGNATURE----- From Christian.Maeder at dfki.de Thu Feb 5 04:58:30 2009 From: Christian.Maeder at dfki.de (Christian Maeder) Date: Thu Feb 5 21:42:27 2009 Subject: [Haskell-beginners] mind your head, was: Parsing a file with data divided into sections In-Reply-To: References: Message-ID: <498AB846.5010509@dfki.de> Magnus Therning wrote: >> isSection line = not . isSpace . head $ line I'ld be more careful with "head"! Imagine your binary fails with: Prelude.head: empty list > countDays [] = [] > countDays ls = let > day = head ls > count = length $ takeWhile (isSpace . head) $ tail ls > in (day, count) : countDays (drop (1 + count) ls) here too, and better use a pattern like: ls@(hd, tl) Cheers Christian From bugfact at gmail.com Thu Feb 5 17:16:56 2009 From: bugfact at gmail.com (Peter Verswyvelen) Date: Thu Feb 5 21:42:28 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Just how unsafe is unsafe In-Reply-To: <498B5BF3.5060405@pikewerks.com> References: <498B5BF3.5060405@pikewerks.com> Message-ID: I do have asked myself the question whether a "really random generating" function could be regarded as "pure" somehow (actually would a true random function still be a mathematical function?) E.g. the function would return a true (not pseudo) random number, practically unpredictable (e.g. hardware assisted, using some physical phenomenon, e.g. using atmospheric noise or something). So you surely won't get referential transparency but since the function is really random, this would be correct behavior? Of course you could just put this random generator in the IO monad, but certain algorithms- like Monte Carlo - intuitively don't seem to operate in a IO monad to me. Okay, just some thoughts from someone who knows absolutely nothing about category theory or advanced computer science, so don't shoot me ;-) On Thu, Feb 5, 2009 at 10:36 PM, Jake McArthur wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Andrew Wagner wrote: > | I understand that unsafeXXX allows impurity, which defiles our ability > | to reason logically about haskell programs like we would like to. My > | question is, to what extent is this true? > > My opinion is that unsafeXXX is acceptable only when its use is > preserved behind an abstraction that is referentially transparent and > type safe. Others may be able to help refine this statement. > > | Suppose we had a module, UnsafeRandoms, which had a function that would > | allow you to generate a different random number every time you call it. > | The semantics are relatively well-defined, impurity is safely sectioned > | off in its own impure module, which is clearly labeled as such. How much > | damage does this do? > > This does not preserve referential transparency, so by my criteria above > this is an unacceptable use of an unsafe function. One reason it's a bad > idea is that it removes determinism, which may be very important for > testability. > > - - Jake > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.9 (GNU/Linux) > Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org > > iEYEARECAAYFAkmLW/MACgkQye5hVyvIUKniOACfQGPLiY65+eiMfsv7BlbYLI++ > Bd0An1N5wp6TDkJzhmdw831/Gj45Bv9S > =TnQg > -----END PGP SIGNATURE----- > > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090205/7eb748bf/attachment.htm From tom.davie at gmail.com Fri Feb 6 02:08:54 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Fri Feb 6 01:58:57 2009 Subject: [Haskell-beginners] Just how unsafe is unsafe In-Reply-To: References: Message-ID: <5C7FA92D-43B3-4894-ACD4-BF7CDE8C0960@gmail.com> On 5 Feb 2009, at 22:11, Andrew Wagner wrote: > So we all know the age-old rule of thumb, that unsafeXXX is simply > evil and anybody that uses it should be shot (except when it's ok). > > I understand that unsafeXXX allows impurity, which defiles our > ability to reason logically about haskell programs like we would > like to. My question is, to what extent is this true? > > Suppose we had a module, UnsafeRandoms, which had a function that > would allow you to generate a different random number every time you > call it. The semantics are relatively well-defined, impurity is > safely sectioned off in its own impure module, which is clearly > labeled as such. How much damage does this do? The problem here is composability ? you have no idea how far your non referentially transparent code has spread, because you can compose functions together willy nilly, meaning your random numbers can get pushed through all sorts of things, and cause odd behaviors (e.g. if a constant happens to get evaluated twice rather than once, and return different values each time). > Can we push the lines elsewhere? Is sectioning unsafeXXX into Unsafe > modules a useful idiom that we can use for other things as well? Well not useful modules, but useful types instead. The point of IO for example is to deliberately construct an environment in which you can't get one of your unsafe values out into the referentially transparent world ? the IO type denotes the line on which one side contains unsafe values, and the other side does not. There are however some instances where unsafe functions *are* safe, Conal's unamb function for example, always returns the same value (as long as its precondition is met), even though it contains IO based code to race the values. There are also some instances where unsafe functions are safe purely through force of will. For example: type ResourcePath = FilePath loadImageResource :: ResourcePath -> Image loadImageResource = unsafePerformIO . loadImage =<< readFile This is safe iff you treat the resource as a part of your program, just like your program's code, if it changes, the world falls down, but as long as it's still there and still the same, you're entirely safe. Bob From barsoap at web.de Fri Feb 6 02:15:23 2009 From: barsoap at web.de (Achim Schneider) Date: Fri Feb 6 02:10:01 2009 Subject: [Haskell-beginners] Re: Just how unsafe is unsafe References: <498B5BF3.5060405@pikewerks.com> Message-ID: <20090206081523.1eba94fe@solaris> Peter Verswyvelen wrote: > I do have asked myself the question whether a "really random > generating" function could be regarded as "pure" somehow (actually > would a true random function still be a mathematical function?) > Wasn't there some agreement some time ago on this list that the universe itself is pure and computers are just simulating impurity by being, essentially, state monads on steroids? -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited. From Christian.Maeder at dfki.de Fri Feb 6 03:47:45 2009 From: Christian.Maeder at dfki.de (Christian Maeder) Date: Fri Feb 6 03:37:38 2009 Subject: [Haskell-beginners] Re: mind your head, was: Parsing a file with data divided into sections In-Reply-To: <498AB846.5010509@dfki.de> References: <498AB846.5010509@dfki.de> Message-ID: <498BF931.8030807@dfki.de> I wrote: > Magnus Therning wrote: >>> isSection line = not . isSpace . head $ line > > I'ld be more careful with "head"! Imagine your binary fails with: > > Prelude.head: empty list see also http://haskell.org/haskellwiki/Haskell_programming_tips#Partial_functions_like_fromJust_and_head >> countDays [] = [] >> countDays ls = let >> day = head ls >> count = length $ takeWhile (isSpace . head) $ tail ls >> in (day, count) : countDays (drop (1 + count) ls) > > here too, and better use a pattern like: ls@(hd, tl) oops, the pattern should be: ls@(hd : tl) Cheers again Christian From magnus at therning.org Fri Feb 6 04:52:28 2009 From: magnus at therning.org (Magnus Therning) Date: Fri Feb 6 04:42:27 2009 Subject: [Haskell-beginners] Re: mind your head, was: Parsing a file with data divided into sections In-Reply-To: <498BF931.8030807@dfki.de> References: <498AB846.5010509@dfki.de> <498BF931.8030807@dfki.de> Message-ID: On Fri, Feb 6, 2009 at 8:47 AM, Christian Maeder wrote: > I wrote: >> Magnus Therning wrote: >>>> isSection line = not . isSpace . head $ line >> >> I'ld be more careful with "head"! Imagine your binary fails with: >> >> Prelude.head: empty list > > see also > http://haskell.org/haskellwiki/Haskell_programming_tips#Partial_functions_like_fromJust_and_head > >>> countDays [] = [] >>> countDays ls = let >>> day = head ls >>> count = length $ takeWhile (isSpace . head) $ tail ls >>> in (day, count) : countDays (drop (1 + count) ls) >> >> here too, and better use a pattern like: ls@(hd, tl) > > oops, the pattern should be: ls@(hd : tl) Another course of action would be to add exception handling; if head throws an exception then the input file isn't following the accepted syntax. /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus?therning?org Jabber: magnus?therning?org http://therning.org/magnus identi.ca|twitter: magthe From Christian.Maeder at dfki.de Fri Feb 6 05:30:33 2009 From: Christian.Maeder at dfki.de (Christian Maeder) Date: Fri Feb 6 05:20:27 2009 Subject: [Haskell-beginners] Re: mind your head, was: Parsing a file with data divided into sections In-Reply-To: References: <498AB846.5010509@dfki.de> <498BF931.8030807@dfki.de> Message-ID: <498C1149.6040001@dfki.de> Magnus Therning wrote: [...] >>>>> isSection line = not . isSpace . head $ line In this particular case I would use: isSection = null . takeWhile isSpace >>> Prelude.head: empty list >> see also >> http://haskell.org/haskellwiki/Haskell_programming_tips#Partial_functions_like_fromJust_and_head > > Another course of action would be to add exception handling; if head > throws an exception then the input file isn't following the accepted > syntax. I'ld rather check all lines before (or filter non empty ones) than trying to catch Prelude.head: empty list! C. From magnus at therning.org Fri Feb 6 05:40:15 2009 From: magnus at therning.org (Magnus Therning) Date: Fri Feb 6 05:30:44 2009 Subject: [Haskell-beginners] Re: mind your head, was: Parsing a file with data divided into sections In-Reply-To: <498C1149.6040001@dfki.de> References: <498AB846.5010509@dfki.de> <498BF931.8030807@dfki.de> <498C1149.6040001@dfki.de> Message-ID: On Fri, Feb 6, 2009 at 10:30 AM, Christian Maeder wrote: [..] >> Another course of action would be to add exception handling; if head >> throws an exception then the input file isn't following the accepted >> syntax. > > I'ld rather check all lines before (or filter non empty ones) than > trying to catch Prelude.head: empty list! Yes, that's how I modified my own "solution" once I tracked down what sort of input it would fail on: main = interact (unlines . map show . countDays . dropWhile null . lines) /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus?therning?org Jabber: magnus?therning?org http://therning.org/magnus identi.ca|twitter: magthe From aslatter at gmail.com Fri Feb 6 07:00:21 2009 From: aslatter at gmail.com (Antoine Latter) Date: Fri Feb 6 06:50:20 2009 Subject: [Haskell-beginners] Just how unsafe is unsafe In-Reply-To: References: Message-ID: <694519c50902060400ma5b5834nb333157f90942e97@mail.gmail.com> On Thu, Feb 5, 2009 at 3:11 PM, Andrew Wagner wrote: > So we all know the age-old rule of thumb, that unsafeXXX is simply evil and > anybody that uses it should be shot (except when it's ok). > I understand that unsafeXXX allows impurity, which defiles our ability to > reason logically about haskell programs like we would like to. My question > is, to what extent is this true? Tangential to all of this - sometimes my unsafeXXX functions are pure, but partial. So I'll have: foo :: a -> b -> Maybe c and unsafeFoo :: a -> b -> c -Antoine From vandijk.roel at gmail.com Fri Feb 6 09:40:47 2009 From: vandijk.roel at gmail.com (Roel van Dijk) Date: Fri Feb 6 09:30:46 2009 Subject: [Haskell-beginners] Just how unsafe is unsafe In-Reply-To: <694519c50902060400ma5b5834nb333157f90942e97@mail.gmail.com> References: <694519c50902060400ma5b5834nb333157f90942e97@mail.gmail.com> Message-ID: On Fri, Feb 6, 2009 at 1:00 PM, Antoine Latter wrote: > Tangential to all of this - sometimes my unsafeXXX functions are pure, > but partial. ?So I'll have: > > foo :: a -> b -> Maybe c > > and > > unsafeFoo :: a -> b -> c I use the "unsafe" prefix in the same way. For me it means 'assume that preconditions hold'. If the preconditions do not hold and you evaluate an unsafe function anyway I would expect an error, as opposed to an exception. I have done that in my (tiny) roman numerals package. -- simplified toRoman :: Int -> Either String Int unsafeToRoman :: Int -> String The first function is very clear about the fact that something can go wrong. If you provide it with a value of (-3) it will (hopefully) produce something like 'Left "no negative numbers allowed"'. The second function hides this fact and will result in a (uncatchable) runtime error. It is still a pure function, but preventing errors is now the responsibility of whoever evaluates it. From colin at colina.demon.co.uk Fri Feb 6 10:10:11 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Fri Feb 6 10:00:11 2009 Subject: [Haskell-cafe] Re: [Haskell-beginners] Just how unsafe is unsafe In-Reply-To: (Roel van Dijk's message of "Fri\, 6 Feb 2009 15\:40\:47 +0100") References: <694519c50902060400ma5b5834nb333157f90942e97@mail.gmail.com> Message-ID: >>>>> "Roel" == Roel van Dijk writes: Roel> On Fri, Feb 6, 2009 at 1:00 PM, Antoine Latter wrote: >> Tangential to all of this - sometimes my unsafeXXX functions >> are pure, but partial. ?So I'll have: >> >> foo :: a -> b -> Maybe c >> >> and >> >> unsafeFoo :: a -> b -> c Roel> I use the "unsafe" prefix in the same way. For me it means Roel> 'assume that preconditions hold'. If the preconditions do Roel> not hold and you evaluate an unsafe function anyway I would Roel> expect an error, as opposed to an exception. I have done Roel> that in my (tiny) roman numerals package. Roel> -- simplified toRoman :: Int -> Either String Int Roel> unsafeToRoman :: Int -> String Roel> The first function is very clear about the fact that Roel> something can go wrong. If you provide it with a value of Roel> (-3) it will (hopefully) produce something like 'Left "no Roel> negative numbers allowed"'. The second function hides this Roel> fact and will result in a (uncatchable) runtime error. It is Roel> still a pure function, but preventing errors is now the Roel> responsibility of whoever evaluates it. Do you document the preconditions? It seems to me that this is more useful than naming a function unsafeXXX. I was using comments to document the contracts on my functions, but I have just found about about ESC/Haskell, so I am now using the contract notation of that (not yet released) tool. See http://www.cl.cam.ac.uk/~nx200/ -- Colin Adams Preston Lancashire From vandijk.roel at gmail.com Fri Feb 6 13:25:18 2009 From: vandijk.roel at gmail.com (Roel van Dijk) Date: Fri Feb 6 13:15:17 2009 Subject: [Haskell-cafe] Re: [Haskell-beginners] Just how unsafe is unsafe In-Reply-To: References: <694519c50902060400ma5b5834nb333157f90942e97@mail.gmail.com> Message-ID: > Do you document the preconditions? Yes. The 'safe' variants of those functions have all preconditions listed in the accompanying (haddock) comments. The 'unsafe' variants simply state that they promote exceptions to errors. > It seems to me that this is more useful than naming a function > unsafeXXX. Well, I do both :-) They are called unsafeXXX and they state why they are unsafe. > I was using comments to document the contracts on my functions, but I > have just found about about ESC/Haskell, so I am now using the > contract notation of that (not yet released) tool. > > See http://www.cl.cam.ac.uk/~nx200/ That is interesting. I like formal proofs and preconditions better than informal ones. From vandijk.roel at gmail.com Fri Feb 6 13:38:11 2009 From: vandijk.roel at gmail.com (Roel van Dijk) Date: Fri Feb 6 13:28:16 2009 Subject: [Haskell-cafe] Re: [Haskell-beginners] Just how unsafe is unsafe In-Reply-To: References: <694519c50902060400ma5b5834nb333157f90942e97@mail.gmail.com> Message-ID: On Fri, Feb 6, 2009 at 5:22 PM, Alberto G. Corona wrote: > then Data.List.head ? Data.Maybe.fromMaybe etc are also unsafe?. Yes, I consider them unsafe. Whenever I see those functions I know that I have to look elsewhere to see if their preconditions hold. I would have preferred that listToMaybe was called head and the existing head called unsafeHead, partialHead or something else of that nature. > unsafe does > not mean "with possible errors". unsafeXXX convert something in the IO monad > into something that is not. So it can potentially contaminate your pure > code. > But Data.List.head applied to a empty list ?will interrupt the computation > abruptly, so your code using head will either run side effect free or not > run at all. I guess what unsafe should mean is a matter of taste. Personally I find correctness more important that pureness. An unsafe function will crash your program if evaluated when its preconditions do not hold. Whether that is because of impurity (segmentation fault?), a partial pattern match or a direct error "bla" is not that important. It might be important when determining why your program crashed, but the result is still the same. The ByteString library has a module called Data.ByteString.Unsafe with plenty of unsafeXXX functions. The comment for unsafeHead for example states: "A variety of head for non-empty ByteStrings. unsafeHead omits the check for the empty case, so there is an obligation on the programmer to provide a proof that the ByteString is non-empty." That perfectly reflects my own philosophy on this issue. From bieffe62 at gmail.com Sat Feb 7 15:29:39 2009 From: bieffe62 at gmail.com (Francesco Bochicchio) Date: Sat Feb 7 15:19:34 2009 Subject: [Haskell-beginners] Appending to a list Message-ID: Hi all, in my haskell exercises I often build list by appending values at the end. But I read somewhere that in haskell this is inefficient since there is no 'pointer to the tail of the list'. I've also seen some example of recursive functions which build the list tail-first and then in the base case of the recursion returns the reverse of the accumulated results, counting on the fact that in haskell 'reverse list' just means 'consume the list from the tail'. Just out of curiosity (I have no need to speed up my little programs with which I try to teach myself some haskell): is this a consolidated pattern? And are append really expensive? Ciao ------- FB -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090207/e53cdee4/attachment.htm From thestonetable at gmail.com Sat Feb 7 16:04:06 2009 From: thestonetable at gmail.com (Cory Knapp) Date: Sat Feb 7 15:54:04 2009 Subject: [Haskell-beginners] Appending to a list In-Reply-To: References: Message-ID: <498DF746.7030702@gmail.com> In general, you want to be building a list "from the front". Consider the list constructor-- x:xs is a list, when x is an element, and xs is a list; on the other hand, xs:x will give you a type error. I think the lisp syntax is a bit more elucidating; in lisp, you use "cons" to create a pair e.g. (cons 1 2), and to create a list, you make a pair whose last element is empty, and cons elements to the front. E.g. (cons 2 '()) gives you the list '(2), which is lisp for [2], and (cons 1 (cons 2 (cons 3 (cons 4 '() ) ) ) ) gives you '(1 2 3 4)-- lisp for [1,2,3,4]). In order to add the end of the list, you need to unravel the whole list, (replacing the '() at the end with "(cons 5 '())" ). On the other hand, adding to the front requires you to just cons another value to it. Haskell works the same way, but it uses an infix operator [1,2,3,4] = 1:2:3:4:[] = 1 : (2 : (3 : (4 : [] ) ) ). So appending to the list is expensive, while adding to the front just requires x : list. Obviously, if you're actually concatenating two lists, you need to filter through one of them anyway, but if you're just putting an element on, it's better to put it on the front. Normally, this is practically accomplished by making recursive procedures which work towards the end of the list. For example, map will apply a function to the first element and then map to the rest: map f (x:xs) = (f x) : (map f xs) map _ [] = [] So, you use your list as a stack-- pulling everything off, and then placing it all back on with the function applied. Does that help, or did I miss the point? Cheers, Cory Knapp Francesco Bochicchio wrote: > Hi all, > > in my haskell exercises I often build list by appending values at the end. > But I read somewhere that in haskell this is inefficient since there > is no > 'pointer to the tail of the list'. I've also seen some example of > recursive > functions which build the list tail-first and then in the base case of the > recursion returns the reverse of the accumulated results, counting on > the fact > that in haskell 'reverse list' just means 'consume the list from the > tail'. > > Just out of curiosity (I have no need to speed up my little programs > with which I try to teach myself > some haskell): is this a consolidated pattern? And are append really > expensive? > > Ciao > ------- > FB > ------------------------------------------------------------------------ > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > From shooshpanchick at gmail.com Sat Feb 7 20:50:17 2009 From: shooshpanchick at gmail.com (Tymur Porkuian) Date: Sat Feb 7 20:40:11 2009 Subject: [Haskell-beginners] Installing packages Message-ID: <7f22364a0902071750t1337567o41a0f6a3c21075e9@mail.gmail.com> I'm trying to install wxcore-0.11.0 using Cabal. I've downloaded it from http://hackage.haskell.org/cgi-bin/hackage-scripts/package/wxcore-0.11.0, unpacked and tried to follow instructions from http://haskell.org/haskellwiki/Cabal/How_to_install_a_Cabal_package, but this is what I'm getting: D:\libraries\wxcore-0.11.0>runhaskell Setup configure Setup: sh: runGenProcess: does not exist (No such file or directory) What does this mean? From allbery at ece.cmu.edu Sat Feb 7 22:42:15 2009 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Sat Feb 7 22:32:36 2009 Subject: [Haskell-beginners] Installing packages In-Reply-To: <7f22364a0902071750t1337567o41a0f6a3c21075e9@mail.gmail.com> References: <7f22364a0902071750t1337567o41a0f6a3c21075e9@mail.gmail.com> Message-ID: <61CA83FD-E615-4070-98B1-3BB034A6DB6F@ece.cmu.edu> On 2009 Feb 7, at 20:50, Tymur Porkuian wrote: > I'm trying to install wxcore-0.11.0 using Cabal. I've downloaded it > from http://hackage.haskell.org/cgi-bin/hackage-scripts/package/wxcore-0.11.0 > , > unpacked and tried to follow instructions from > http://haskell.org/haskellwiki/Cabal/How_to_install_a_Cabal_package, > but this is what I'm getting: > > D:\libraries\wxcore-0.11.0>runhaskell Setup configure > Setup: sh: runGenProcess: does not exist (No such file or directory) > > What does this mean? On Windows it usually means that the package has a "configure" shell script and therefore requires that Cygwin or MSYS be installed. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 195 bytes Desc: This is a digitally signed message part Url : http://www.haskell.org/pipermail/beginners/attachments/20090207/2d6072e9/PGP-0001.bin From mad.one at gmail.com Sun Feb 8 02:45:45 2009 From: mad.one at gmail.com (Austin Seipp) Date: Sun Feb 8 02:35:41 2009 Subject: [Haskell-beginners] Just how unsafe is unsafe In-Reply-To: References: Message-ID: <1234079140-sup-7301@existential.local> Excerpts from Andrew Wagner's message of Thu Feb 05 15:11:17 -0600 2009: > My question is, to what extent is this true? You can completely destroy the soundness of the type system: import Data.IORef import System.IO.Unsafe import Control.Monad cast :: a -> b cast x = f where f = unsafePerformIO $ do writeIORef r [x] b <- liftM head $ readIORef r return b Austin From bieffe62 at gmail.com Sun Feb 8 03:24:30 2009 From: bieffe62 at gmail.com (Francesco Bochicchio) Date: Sun Feb 8 03:14:24 2009 Subject: [Haskell-beginners] Appending to a list In-Reply-To: <498DF746.7030702@gmail.com> References: <498DF746.7030702@gmail.com> Message-ID: 2009/2/7 Cory Knapp > > Does that help, or did I miss the point? > > Ok, I'll try to be more clear with an example: the following function - which surely can be written in better way - takes a list and a predicate and builds two lists. a list of lists of consecutive elements that satisfy the predicate and a list of separators, i.e. of elements that does not satisfy the predicate. That is: groups odd [1,3,2,5,9,6] -> [[1,3],[5,9]], [2,6] The function uses another function, groupWhile, which works like takeWhile but returns also the rest of the list. Now, from the way the function works, it shoud build the two result lists by appending new elements to them. But, as you said, appending is expensive in haskell, so instead I build the lists using (:), which gives me the list in reverse order, and then I use the 'final step' of the function - the base case of the recursion - to reverse the result. If I understand lazyness, this should be a low-cost operation because it does not actual build a reversed list, but only make the list to be 'consumed' from the tail. Now, this trick is not mine: I read it somewhere on internet (I can'tremember where), so I was asking if it is classified among the 'neat tricks' or among the 'ugly hacks' :-) Here is the code I was referring to: groups :: (a->Bool)-> [a] -> ([[a]],[a]) groups f lst = groups_ f ([],[]) lst where groups_ f (gs,seps) [] = (reverse gs, reverse seps) groups_ f (gs,seps) [a] = if (f a) then ( reverse ( [a]:gs), reverse seps ) else ( reverse gs , reverse (a:seps) ) groups_ f (gs, seps) lst = groups_ f (g:gs, r:seps) est where (g, (r:est)) = groupWhile f lst Ciao ------- FB -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090208/6396d453/attachment.htm From aneumann at inf.fu-berlin.de Sun Feb 8 03:26:41 2009 From: aneumann at inf.fu-berlin.de (Adrian Neumann) Date: Sun Feb 8 03:16:54 2009 Subject: [Haskell-beginners] Appending to a list In-Reply-To: References: Message-ID: <11B28DBD-EC37-4C0D-8592-37D9DE86C2EF@inf.fu-berlin.de> Yes, appending to the tail of a list is an expensive operation. You may ask yourself why there is no pointer to the end of a list. That's because the end is in general not known (e.g. if the list is produced by a computation, or if it's infinite). However if you know up front that your list will be finite and you don't rely on lazyness you may want to use a Data.Sequence instead > http://www.haskell.org/ghc/docs/latest/html/libraries/containers/ Data-Sequence.html Cheers, Adrian Am 07.02.2009 um 21:29 schrieb Francesco Bochicchio: > Hi all, > > in my haskell exercises I often build list by appending values at > the end. > But I read somewhere that in haskell this is inefficient since > there is no > 'pointer to the tail of the list'. I've also seen some example of > recursive > functions which build the list tail-first and then in the base case > of the > recursion returns the reverse of the accumulated results, counting > on the fact > that in haskell 'reverse list' just means 'consume the list from > the tail'. > > Just out of curiosity (I have no need to speed up my little > programs with which I try to teach myself > some haskell): is this a consolidated pattern? And are append > really expensive? > > Ciao > ------- > FB > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 194 bytes Desc: Signierter Teil der Nachricht Url : http://www.haskell.org/pipermail/beginners/attachments/20090208/0e9cb17f/PGP.bin From apfelmus at quantentunnel.de Sun Feb 8 05:57:47 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Sun Feb 8 05:47:06 2009 Subject: [Haskell-beginners] Re: Appending to a list In-Reply-To: References: <498DF746.7030702@gmail.com> Message-ID: Francesco Bochicchio wrote: > But, as you said, appending is expensive in haskell We can say how expensive. Namely, fully evaluating xs ++ ys takes O(length xs) time. Always appending an element at the end will lead to something like (..((([1] ++ [2]) ++ [3]) ++ [4]) ++ ..) ++ [n] which will take O(n^2) time instead of linear time. This is probably best demonstrated with the following two implementations of reverse reverse1 [] = [] reverse1 (x:xs) = reverse1 xs ++ [x] reverse2 xs = go [] xs where go ys [] = ys go ys (x:xs) = go (x:ys) xs The first runs in quadratic time while second runs in linear time. > so instead I build the lists using (:), which gives me the list in > reverse order, and then I use the 'final step' of the function - the > base case of the recursion - to reverse the result. If I understand > laziness, this should be a low-cost operation because it does not > actual build a reversed list, but only make the list to be > 'consumed' from the tail. No, reverse has nothing to do with laziness and still costs O(n) time. It's just that building the list in linear time and then reversing it in linear time is cheaper than building the list in quadratic time. > Here is the code I was referring to: > > groups :: (a->Bool)-> [a] -> ([[a]],[a]) > groups f lst = groups_ f ([],[]) lst where > groups_ f (gs,seps) [] = (reverse gs, reverse seps) > groups_ f (gs,seps) [a] = if (f a) > then ( reverse ( [a]:gs), reverse seps ) > else ( reverse gs , reverse (a:seps) ) > groups_ f (gs, seps) lst = groups_ f (g:gs, r:seps) est > where > (g, (r:est)) = groupWhile f lst While using reverse instead of appending at the end of the list is a good idea, not building the list in reverse at all is much better. First, let me restate your code as groups p xs = go ([],[]) xs where go (gs,seps) xs = let (g,rest) = span p xs in case rest of r:est -> go (g:gs, r:seps) est [] -> (reverse (g:gs), reverse seps) The groupWhile function can be found in the Prelude, it's called span . This function groups differs from yours, for instance we have groups odd [2,2,2] == ([[],[],[],[]],[2,2,2]) groups odd [1,2] == ([[1],[]],[2]) groups odd [1,1] == ([[1,1]],[]) By the way, your code crashes in the last case. Now, let's reformulate it so that the result won't be built in reverse. The key is to eliminate the unnecessary accumulating parameter and work with the result of the recursive call to groups directly: groups p xs = let (g,rest) = span p xs in case rest of r:est -> let (gs,seps) = groups p est in (g:gs,r:seps) [] -> ([g], []) I'd say that this is the canonical implementation. In case you wrote this function to split strings, have a look at http://hackage.haskell.org/cgi-bin/hackage-scripts/package/split Regards, apfelmus -- http://apfelmus.nfshost.com From mad.one at gmail.com Sun Feb 8 14:43:46 2009 From: mad.one at gmail.com (Austin Seipp) Date: Sun Feb 8 14:33:41 2009 Subject: [Haskell-beginners] Just how unsafe is unsafe In-Reply-To: <1234079140-sup-7301@existential.local> References: <1234079140-sup-7301@existential.local> Message-ID: <1234122181-sup-891@existential.local> Excerpts from Austin Seipp's message of Sun Feb 08 01:45:45 -0600 2009: > ... code ... > > Austin *smacks head* import Data.IORef import System.IO.Unsafe import Control.Monad cast :: a -> b cast x = f where f = unsafePerformIO $ do writeIORef r [x] b <- liftM head $ readIORef r return b r = unsafePerformIO $ newIORef [] From shooshpanchick at gmail.com Sun Feb 8 17:27:57 2009 From: shooshpanchick at gmail.com (Tymur Porkuian) Date: Sun Feb 8 17:17:48 2009 Subject: [Haskell-beginners] Installing packages In-Reply-To: <61CA83FD-E615-4070-98B1-3BB034A6DB6F@ece.cmu.edu> References: <7f22364a0902071750t1337567o41a0f6a3c21075e9@mail.gmail.com> <61CA83FD-E615-4070-98B1-3BB034A6DB6F@ece.cmu.edu> Message-ID: <7f22364a0902081427k7fa96cb8tc1b0efa1ec669441@mail.gmail.com> >> I'm trying to install wxcore-0.11.0 using Cabal. I've downloaded it >> from >> http://hackage.haskell.org/cgi-bin/hackage-scripts/package/wxcore-0.11.0, >> unpacked and tried to follow instructions from >> http://haskell.org/haskellwiki/Cabal/How_to_install_a_Cabal_package, >> but this is what I'm getting: >> >> D:\libraries\wxcore-0.11.0>runhaskell Setup configure >> Setup: sh: runGenProcess: does not exist (No such file or directory) >> >> What does this mean? > > On Windows it usually means that the package has a "configure" shell script > and therefore requires that Cygwin or MSYS be installed. I have installed Cygwin, and still getting the exact same error. Should something else be done after installing it? From gtener at gmail.com Sun Feb 8 18:09:50 2009 From: gtener at gmail.com (=?UTF-8?Q?Krzysztof_Skrz=C4=99tnicki?=) Date: Sun Feb 8 17:59:42 2009 Subject: [Haskell-beginners] Installing packages In-Reply-To: <7f22364a0902081427k7fa96cb8tc1b0efa1ec669441@mail.gmail.com> References: <7f22364a0902071750t1337567o41a0f6a3c21075e9@mail.gmail.com> <61CA83FD-E615-4070-98B1-3BB034A6DB6F@ece.cmu.edu> <7f22364a0902081427k7fa96cb8tc1b0efa1ec669441@mail.gmail.com> Message-ID: <220e47b40902081509r5de89ec5o1f5ebfd1168ad963@mail.gmail.com> On Sun, Feb 8, 2009 at 23:27, Tymur Porkuian wrote: >>> I'm trying to install wxcore-0.11.0 using Cabal. I've downloaded it >>> from >>> http://hackage.haskell.org/cgi-bin/hackage-scripts/package/wxcore-0.11.0, >>> unpacked and tried to follow instructions from >>> http://haskell.org/haskellwiki/Cabal/How_to_install_a_Cabal_package, >>> but this is what I'm getting: >>> >>> D:\libraries\wxcore-0.11.0>runhaskell Setup configure >>> Setup: sh: runGenProcess: does not exist (No such file or directory) >>> >>> What does this mean? >> >> On Windows it usually means that the package has a "configure" shell script >> and therefore requires that Cygwin or MSYS be installed. > > I have installed Cygwin, and still getting the exact same error. > Should something else be done after installing it? Are you running "cabal install" from within Cygwin prompt? All best Christopher Skrz?tnicki From shooshpanchick at gmail.com Sun Feb 8 18:21:18 2009 From: shooshpanchick at gmail.com (Tymur Porkuian) Date: Sun Feb 8 18:11:11 2009 Subject: [Haskell-beginners] Installing packages In-Reply-To: <220e47b40902081509r5de89ec5o1f5ebfd1168ad963@mail.gmail.com> References: <7f22364a0902071750t1337567o41a0f6a3c21075e9@mail.gmail.com> <61CA83FD-E615-4070-98B1-3BB034A6DB6F@ece.cmu.edu> <7f22364a0902081427k7fa96cb8tc1b0efa1ec669441@mail.gmail.com> <220e47b40902081509r5de89ec5o1f5ebfd1168ad963@mail.gmail.com> Message-ID: <7f22364a0902081521n1cbdfb22t99506d7e3bcf920b@mail.gmail.com> >>>> I'm trying to install wxcore-0.11.0 using Cabal. I've downloaded it >>>> from >>>> http://hackage.haskell.org/cgi-bin/hackage-scripts/package/wxcore-0.11.0, >>>> unpacked and tried to follow instructions from >>>> http://haskell.org/haskellwiki/Cabal/How_to_install_a_Cabal_package, >>>> but this is what I'm getting: >>>> >>>> D:\libraries\wxcore-0.11.0>runhaskell Setup configure >>>> Setup: sh: runGenProcess: does not exist (No such file or directory) >>>> >>>> What does this mean? >>> >>> On Windows it usually means that the package has a "configure" shell script >>> and therefore requires that Cygwin or MSYS be installed. >> >> I have installed Cygwin, and still getting the exact same error. >> Should something else be done after installing it? > > Are you running "cabal install" from within Cygwin prompt? No, I'm not running "cabal install", I'm running "runhaskell Setup configure" (as written in http://haskell.org/haskellwiki/Cabal/How_to_install_a_Cabal_package). "cabal" is not even on the PATH, actually. Now I launched this command from cygwin, this is what I got: .../cygdrive/d/libraries/wxcore-0.11.0 $ runhaskell.exe Setup configure warning: Unable to find wxWidgets configuration (wx-config). checking system: error: Unable to find the 'wx-config' program: wx-config Maybe you forgot to run 'make install' on wxWidgets? Otherwise, add the install directory of wx-config to your path. Or maybe you are trying to compile with Microsoft Visual C++? If so, you can specify that on the command line: For example: ./configure --with-msc What is wx-config and where can I get it? From gtener at gmail.com Sun Feb 8 18:27:19 2009 From: gtener at gmail.com (=?UTF-8?Q?Krzysztof_Skrz=C4=99tnicki?=) Date: Sun Feb 8 18:17:11 2009 Subject: [Haskell-beginners] Installing packages In-Reply-To: <7f22364a0902081521n1cbdfb22t99506d7e3bcf920b@mail.gmail.com> References: <7f22364a0902071750t1337567o41a0f6a3c21075e9@mail.gmail.com> <61CA83FD-E615-4070-98B1-3BB034A6DB6F@ece.cmu.edu> <7f22364a0902081427k7fa96cb8tc1b0efa1ec669441@mail.gmail.com> <220e47b40902081509r5de89ec5o1f5ebfd1168ad963@mail.gmail.com> <7f22364a0902081521n1cbdfb22t99506d7e3bcf920b@mail.gmail.com> Message-ID: <220e47b40902081527m10075796l41854116e5029fa5@mail.gmail.com> On Mon, Feb 9, 2009 at 00:21, Tymur Porkuian wrote: >> >> Are you running "cabal install" from within Cygwin prompt? > > No, I'm not running "cabal install", I'm running "runhaskell Setup > configure" (as written in > http://haskell.org/haskellwiki/Cabal/How_to_install_a_Cabal_package). > "cabal" is not even on the PATH, actually. Now I launched this command > from cygwin, this is what I got: > > .../cygdrive/d/libraries/wxcore-0.11.0 > $ runhaskell.exe Setup configure > warning: > Unable to find wxWidgets configuration (wx-config). > > checking system: > error: > Unable to find the 'wx-config' program: wx-config > Maybe you forgot to run 'make install' on wxWidgets? > Otherwise, add the install directory of wx-config to your path. > > Or maybe you are trying to compile with Microsoft Visual C++? > If so, you can specify that on the command line: > For example: ./configure --with-msc > > What is wx-config and where can I get it? > You need wxWidgets sources: get them at http://www.wxwidgets.org/downloads/#latest_stable . After that you need to install them appropriately, so that wx-config will be in PATH. All best Christopher Skrz?tnicki From KMARTINE at altera.com Fri Feb 6 13:25:06 2009 From: KMARTINE at altera.com (Kirk Martinez) Date: Sun Feb 8 21:06:19 2009 Subject: [Haskell-beginners] cabal-install can't connect Message-ID: I'm trying to use cabal-install through the firewall at my work and I am consistently denied: C:\>cabal update -v3 Downloading package list from server 'http://hackage.haskell.org/packages/archive' Sending: GET http://hackage.haskell.org/packages/archive/00-index.tar.gz HTTP/1.1 User-Agent: cabal-install/0.6.0 Creating new connection to hackage.haskell.org cabal: connect: failed (Connection refused (WSAECONNREFUSED)) I built cabal-install 0.6.0 and compiled with ghc 6.10.1 without a hitch. I set my http_proxy variable the same as other apps I use which are able to connect to other sites via http. I even patched cabal-install according to these instructions, but I still get this same "Connection refused". Seems it's not even getting to the proxy. This is on Windows XP SP2. Any help or suggestions would be greatly appreciated! Installing package dependencies by hand is something I thought I left behind in the 90's... Thanks, Kirk Martinez ________________________________ Confidentiality Notice. This message may contain information that is confidential or otherwise protected from disclosure. If you are not the intended recipient, you are hereby notified that any use, disclosure, dissemination, distribution, or copying of this message, or any attachments, is strictly prohibited. If you have received this message in error, please advise the sender by reply e-mail, and delete the message and any attachments. Thank you. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090206/4ef47dcb/attachment.htm From devriese at cs.tcd.ie Fri Feb 6 04:53:52 2009 From: devriese at cs.tcd.ie (Edsko de Vries) Date: Sun Feb 8 21:06:52 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Just how unsafe is unsafe In-Reply-To: <498B5BF3.5060405@pikewerks.com> References: <498B5BF3.5060405@pikewerks.com> Message-ID: <20090206095352.GA11560@netsoc.tcd.ie> Hi, > My opinion is that unsafeXXX is acceptable only when its use is > preserved behind an abstraction that is referentially transparent and > type safe. Others may be able to help refine this statement. I would agree with this. The problem is that impurity spreads easily. For example, suppose we have this truly random number generator, 'random'. As soon as we have this, then *almost every* function is potentially impure: f :: Integer -> Integer f x = random + x g :: [Integer] g = repeat random etc. etc. The compiler has no way of tracking impurity other than through the type system which is, of course, exactly what monads do. To echo the sentiment above, the only safe way to use unsafePerformIO is to hide it behind a function that *is* guaranteed to be pure (i.e., returns the same values for the same arguments, can be inlined, etc.). And even then, I would recommend against it. Let me give a *practical* reason why. For a long time, I would never even have considered unsafePerformIO, but I recently had an application that needed unique global identifiers in lots of places, and I was reluctant to pass state around everywhere; *but* I could hide it in a few functions, which were themselves pure. It looked something like: -- Replace (some) name by a number quote :: Integer -> Term -> Term -- Replace a number by (that) name unquote :: Name -> Term -> Term -- Typical usage foo t == let l = getUnsafeUniqueGlobalIdentifier () in unquote l . do some stuff . quote l Since "unquote l . quote l" is an identity operation, 'foo' itself is pure -- provided that nothing in 'do some stuff' relies on the exact identity of the identifier. --- A rule which I broke at some point, got some very strange behaviour, and took me ages to debug. This was mostly due to laziness, which made the point of execution of the unsafe operation to be very difficult to predict. For example, every call to getUnsafeUniqueGlobalIdentifier (it wasn't actually called that, don't worry :-) yielded a number one higher than the previous. However, in a list of terms [t1, t2, .., tn] all of which include some unique idnetifier, it is *not* the generation of the list that determines whether the identifiers in these terms are incrementing, but the *evaluation* of the list -- when are the terms forced to normal form. I was called 'sort' on this list, and sort depended on the values of these identifiers -- but since sort evaluated the terms in the list to normal form in a hard to predict order, the order of the list was anything but sorted! --- Moreover, you need all sorts of compiler options or nasty hacks (the unit argument to getUnsafeUniqueGlobalIdentifier above is no mistake) to avoid the compiler optimizing your code in ways that you did not expect. In the end, I ended up rewriting the entire application to avoid the use of this global unique identifiers, because it was simply too difficult to get right. I felt I was writing C code again and was chasing bugs due to dangling pointers and the wrong memory being used. Not a time I want to return to! Moral of the story: unless you really really need to and really really know what you are doing -- do not use unsafePerformIO. Uncontrolled side effects and lazines will cause extremely hard to track behaviour in your program, and things are almost guaranteed to go wrong. Edsko From kirby81 at gmail.com Mon Feb 9 01:59:25 2009 From: kirby81 at gmail.com (Salvatore Insalaco) Date: Mon Feb 9 01:49:15 2009 Subject: [Haskell-beginners] cabal-install can't connect In-Reply-To: References: Message-ID: <5a376f550902082259l5c21219encd8c1e7d02c21364@mail.gmail.com> On Fri, Feb 6, 2009 at 7:25 PM, Kirk Martinez wrote: > I'm trying to use cabal-install through the firewall at my work and I am > consistently denied: In my experience, cabal-install ignores the http_proxy variable on Windows, and uses the Internet Explorer proxy registry key. Another problem could be that your proxy is using NTLM authentication, that cabal doesn't support. To solve this problem, if your proxy supports BASIC authentication, just put the proxy informations in the Internet Explorer proxy dialog; you have to do it even if there's the "automatic proxy configuration" setting, as cabal is unable to use it. If your proxy supports NTLM authentication, just download a package like http://www.geocities.com/rozmanov/ntlm/ and then put its host and port as proxy in Internet Explorer. Salvatore From apfelmus at quantentunnel.de Mon Feb 9 05:36:51 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Mon Feb 9 05:26:08 2009 Subject: [Haskell-beginners] Re: Appending to a list In-Reply-To: References: <498DF746.7030702@gmail.com> Message-ID: Francesco Bochicchio wrote: > Heinrich Apfelmus wrote: >> >> No, reverse has nothing to do with laziness and still costs O(n) >> time. It's just that building the list in linear time and then >> reversing it in linear time is cheaper than building the list in >> quadratic time. > > I see. Thanks for the information. I keep thinking to haskell lists > as they are 'generators', but this is not always the case ... and I > realize now that there is no way to reverse the list without > expanding it first. Well, they are 'generators' from an operational point of view, in that elements are generated on demand. But other than that, they are just a tree : / \ 1 : / \ 2 : / \ 3 ... >> Now, let's reformulate it so that the result won't be built in >> reverse. The key is to eliminate the unnecessary accumulating >> parameter and work with the result of the recursive call to groups >> directly: >> >> groups p xs = let (g,rest) = span p xs in >> case rest of >> r:est -> let (gs,seps) = groups p est in (g:gs,r:seps) >> [] -> ([g], []) >> >> I'd say that this is the canonical implementation. > > The reason I used accumulators is that I try to teach myself to > always write tail-recursive functions. I have been bitten by stack > exhaustion in one of my first exercises (working on large amount of > data), so I thought that non tail-recursive functions should be > always avoided. But using accumulators often leads to appending to > lists, so one has to find the balance between the two things... Due to lazy evaluation, something that looks tail recursive is not necessarily tail recursive at all; I strongly advise to unlearn your habit. For example, the version of groups that uses an accumulator is less efficient that the one without. In general, a lazy approach to performance is best: just use the simplest possible implementation and postpone performance considerations to when the program actually takes ages to compute the result. Concerning stack exhaustion and large amounts of data, there is one very common pattern worth knowing, namely foldr vs. foldl' , see also http://en.wikibooks.org/wiki/Haskell/Performance_Introduction#Space http://book.realworldhaskell.org/read/functional-programming.html Other than that, there is no way around understanding Haskell's evaluation model properly. Regards, apfelmus -- http://apfelmus.nfshost.com From poliquin at softcomp.com Mon Feb 9 20:43:03 2009 From: poliquin at softcomp.com (Tom Poliquin) Date: Mon Feb 9 21:10:18 2009 Subject: [Haskell-beginners] Recursive Let Message-ID: <200902091743.03601.poliquin@softcomp.com> I'm working on learning arrows. This has led me to ArrowLoop, which then led me to trying to understand the following, > tracePlus b = let (c,d) = (d,b:d) > in c > > main = do > w <- return $ take 10 $ tracePlus 7 > print w > which yields [7,7,7,7,7,7,7,7,7,7] My confusion two pronged, 1) How let actually 'recurses' 2) How things get started (since d is undefined). I have some vague understanding of both issues but I want to make sure what's *really* going on so I don't base my Haskell learning experience on a house of cards. Help greatly appreciated. My ramblings 1) How does recursion happen? Being an ex-Schemer I recalled that let x = 3 get translated into something like (lambda (x) ... ) 3 So now there's a function involved. It's clear that b:d is (cons b d) another function. So with appropriate plumbing I could see the thing recurses but the Haskell viewpoint eludes me. 2) How do things get started? It seems that Haskell could figure out that 'd' is a list. If an uninitialized (undefined?) list contains [] then things are reasonably straightforward .. tracePlus gets applied to 7 (b:d) then becomes [7] (c,d) then becomes ([],7) Given there's an infinite loop (stream) then 'take' grabs 'c' (an []) and asks for another. Haskell's laziness works for us here. (b:d) then becomes [7,7] (c,d) then becomes (7,[7,7]) ... ... This is all fine. The only thing that subconsciously nags me is that we appear to 'return' each time which would imply that we would leave the closure causing 'd' to be undefined again. I know this isn't true and if I close my eyes, think really hard, and recall how streams are implemented in Scheme (with a value-promise pair; the closure is actually passed around) then I can see how this would all work. Back to the undefined list ... if it's *not* an [] and has something to do with bottom ( _|_ ) then my eyes glaze over and I have to go watch a Woody Allen movie to reset. Sorry for the rambling. I really like Haskell and I have found it very powerful. Any help greatly appreciated. Thanks, Tom From allbery at ece.cmu.edu Mon Feb 9 23:42:23 2009 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Mon Feb 9 23:32:21 2009 Subject: [Haskell-beginners] Recursive Let In-Reply-To: <200902091743.03601.poliquin@softcomp.com> References: <200902091743.03601.poliquin@softcomp.com> Message-ID: <6A551B70-66C4-4A16-8451-4E6F5B458776@ece.cmu.edu> On 2009 Feb 9, at 20:43, Tom Poliquin wrote: > I'm working on learning arrows. > This has led me to ArrowLoop, which then led me > to trying to understand the following, > >> tracePlus b = let (c,d) = (d,b:d) >> in c >> >> main = do >> w <- return $ take 10 $ tracePlus 7 >> print w > > 1) How does recursion happen? > > Being an ex-Schemer I recalled that let x = 3 > get translated into something like > > (lambda (x) ... ) 3 > > So now there's a function involved. It's clear that b:d is > > (cons b d) > > another function. So with appropriate plumbing > I could see the thing recurses but the Haskell viewpoint > eludes me. The trick is that the c and d on both sides of the equal sign are identical. Since this asserts that d = b:d, Haskell repeatedly prepends b to d (lazily, so "take 10" halts the recursion). let (c,d) = (d,b:d) in c = d let (c,d) = (b:d,b:b:d) in c = b:d let (c,d) = (b:b:d,b:b:b:d) in c = b:b:d ... As long as something consumes elements from c, that let will continue to expand recursively. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 195 bytes Desc: This is a digitally signed message part Url : http://www.haskell.org/pipermail/beginners/attachments/20090209/7e0ecc3d/PGP.bin From DekuDekuplex at Yahoo.com Tue Feb 10 02:18:45 2009 From: DekuDekuplex at Yahoo.com (Benjamin L.Russell) Date: Tue Feb 10 02:08:39 2009 Subject: [Haskell-beginners] A Comparison of Haskell and Scheme Message-ID: Although somewhat dated (posted on October 24, 2006 4:39 PM, to be precise), here is an interesting comparison of Haskell and Scheme, by Mark C. Chu-Carroll, a PhD computer scientist who works as a software engineer at Google, on his blog, regarding whether someone should translate Douglas Hofstadter's columns introducing Scheme to replace the Scheme code with Haskell code: Good Math, Bad Math : Haskell and Scheme: Which One and Why? http://scienceblogs.com/goodmath/2006/10/haskell_and_scheme_which_one_a.php The entry discusses differences in syntax, typing, and semantics, and makes for interesting reading. Surprisingly, he states that Haskell syntax is easier to learn for beginners: >I've actually taught an introduction to computer class using Scheme, >and the syntax was a big problem. > >I think that syntactically, Haskell is a better language for beginners. >Haskell syntax is very redundant, which is good for people. Compare >these two little snippets: > >(define (fact n) > (if (= n 0) > 1 > (* n (fact (- n 1))))) > >fact n = if n == 0 > then 1 > else n * fact(n-1) > >Which is easier to read? And the Haskell can get even easier to read >and write using pattern matching: > >fact 0 = 1 >fact n = n * fact (n-1) > >Try this comparison: > >(define (fold init reducer list) > (if (eq? list ()) > init > (reducer (car list) (fold init reducer (cdr list))))) > >versus: > >fold init reducer [] = init >fold init reducer l:ls = reducer l (fold init reducer ls) > >The difference gets much more obvious with bigger pieces of code. >Between the deliberate redundancies in Haskell's syntax, and the way >that pattern matching lets you decompose programs, the Haskell is >significantly clearer. This is the first time that I have seen a claim that Scheme syntax was a big problem compared to Haskell syntax, but his claims make sense. It makes me wonder whether his students were true beginners.... If his claims are true, though, then we probably need a counterpart to SICP (see http://mitpress.mit.edu/sicp/) for Haskell. The closest I can think of is SOE (see http://www.haskell.org/soe/); any alternatives? There's also _The Haskell Road to Logic, Maths and Programming_ (see http://homepages.cwi.nl/~jve/HR/) and _Real World Haskell_ (see http://book.realworldhaskell.org/), but the former is really about using Haskell to learn discrete mathematics and logic, and the latter is not directed toward computer science majors, so they don't correspond very closely. If Haskell is well-suited as a language for beginners, then there shouldn't be any reason for not creating a Haskell alternative. -- Benjamin L. Russell -- Benjamin L. Russell / DekuDekuplex at Yahoo dot com http://dekudekuplex.wordpress.com/ Translator/Interpreter / Mobile: +011 81 80-3603-6725 "Furuike ya, kawazu tobikomu mizu no oto." -- Matsuo Basho^ From krewinkel at gmx.net Tue Feb 10 03:30:40 2009 From: krewinkel at gmx.net (Albert Krewinkel) Date: Tue Feb 10 03:20:34 2009 Subject: [Haskell-beginners] A Comparison of Haskell and Scheme In-Reply-To: (Benjamin L. Russell's message of "Tue, 10 Feb 2009 16:18:45 +0900") References: Message-ID: Benjamin L.Russell writes: > Although somewhat dated (posted on October 24, 2006 4:39 PM, to be > precise), here is an interesting comparison of Haskell and Scheme, by > Mark C. Chu-Carroll, a PhD computer scientist who works as a software > engineer at Google, on his blog, regarding whether someone should > translate Douglas Hofstadter's columns introducing Scheme to replace > the Scheme code with Haskell code: > > Good Math, Bad Math : Haskell and Scheme: Which One and Why? > http://scienceblogs.com/goodmath/2006/10/haskell_and_scheme_which_one_a.php > > The entry discusses differences in syntax, typing, and semantics, and > makes for interesting reading. I've got a question related to comparison of Haskell and Lisp. I just learned some basics about category theory and therefore started to learn some Haskell, too. Currently I'm doing most of my hacking in lisp (to be precise: the probably unpurest language out there, Common Lisp), so please excuse my ignorance as I'm try to change this. Of what I've seen so far, I'm very fascinated by the power and elegance of Haskell. I read a few short introductions on Monads, getting a glimps of easy DSL developing in Haskell. In Lisp, one would use the macro system to achive this. Even though the concepts seem fundamentally different, I was wondering if there are any parallels? Also, could someone point me to a gentle introduction to syntax, semantics and type systems? I understand that lisp-like macros do not exist in Haskell since they would break the type system and could give rise to unclear semantics. I'd like to understand what's going on, so pointers to books or tutorials would be highly appreciated. Thanks Albert > Surprisingly, he states that Haskell > syntax is easier to learn for beginners: > >>I've actually taught an introduction to computer class using Scheme, >>and the syntax was a big problem. >> >>I think that syntactically, Haskell is a better language for beginners. >>Haskell syntax is very redundant, which is good for people. Compare >>these two little snippets: >> >>(define (fact n) >> (if (= n 0) >> 1 >> (* n (fact (- n 1))))) >> >>fact n = if n == 0 >> then 1 >> else n * fact(n-1) >> >>Which is easier to read? And the Haskell can get even easier to read >>and write using pattern matching: >> >>fact 0 = 1 >>fact n = n * fact (n-1) >> >>Try this comparison: >> >>(define (fold init reducer list) >> (if (eq? list ()) >> init >> (reducer (car list) (fold init reducer (cdr list))))) >> >>versus: >> >>fold init reducer [] = init >>fold init reducer l:ls = reducer l (fold init reducer ls) >> >>The difference gets much more obvious with bigger pieces of code. >>Between the deliberate redundancies in Haskell's syntax, and the way >>that pattern matching lets you decompose programs, the Haskell is >>significantly clearer. > > This is the first time that I have seen a claim that Scheme syntax was > a big problem compared to Haskell syntax, but his claims make sense. > It makes me wonder whether his students were true beginners.... > > If his claims are true, though, then we probably need a counterpart to > SICP (see http://mitpress.mit.edu/sicp/) for Haskell. The closest I > can think of is SOE (see http://www.haskell.org/soe/); any > alternatives? There's also _The Haskell Road to Logic, Maths and > Programming_ (see http://homepages.cwi.nl/~jve/HR/) and _Real World > Haskell_ (see http://book.realworldhaskell.org/), but the former is > really about using Haskell to learn discrete mathematics and logic, > and the latter is not directed toward computer science majors, so they > don't correspond very closely. If Haskell is well-suited as a > language for beginners, then there shouldn't be any reason for not > creating a Haskell alternative. > > -- Benjamin L. Russell From DekuDekuplex at Yahoo.com Tue Feb 10 05:03:31 2009 From: DekuDekuplex at Yahoo.com (Benjamin L.Russell) Date: Tue Feb 10 04:53:34 2009 Subject: [Haskell-beginners] Re: A Comparison of Haskell and Scheme References: Message-ID: <6qg2p4902o0ufaknthbqccmrs1k4abisps@4ax.com> On Tue, 10 Feb 2009 00:30:40 -0800, Albert Krewinkel wrote: >Of what I've seen so far, I'm very fascinated by the power and elegance >of Haskell. I read a few short introductions on Monads, getting a >glimps of easy DSL developing in Haskell. In Lisp, one would use the >macro system to achive this. Even though the concepts seem >fundamentally different, I was wondering if there are any parallels? Lisp-style macros enable one to extend Lisp syntax. They take Lisp code as input, and return Lisp code as output. This behavior is closely related to reflection (see http://en.wikipedia.org/wiki/Reflection_(computer_science)), in which a computer program observes and modifies its own structure and behavior. In a related thread on Haskell-Cafe (see "[Haskell-cafe] Re: Monad explanation" at http://www.haskell.org/pipermail/haskell-cafe/2009-February/055052.html), I recently asked about reflection in Haskell: >On Wed, 4 Feb 2009 21:43:04 -0800, Max Rabkin >wrote: > >>On Wed, Feb 4, 2009 at 9:38 PM, Benjamin L. Russell >> wrote: >>> Is it possible to write a self-referential function in Haskell that >>> modifies itself? >> >>Is it possible to write *any* kind of function in Haskell that >>modifies *anything*? > >While trying to research this issue, I came across a relevant archived >thread in Haskell-Cafe, entitled "[Haskell-cafe] haskell and >reflection," started by Greg Meredith, dated "Tue, 11 Sep 2007 >07:09:22 -0700" (see >http://www.mail-archive.com/haskell-cafe@haskell.org/msg29882.html), >which at first had me worried. Specifically, Greg wrote as follows: > >>Am i wrong in my assessment that the vast majority of reflective machinery >>is missing from Haskell? Specifically, >> >> - there is no runtime representation of type available for >> programmatic representation >> - there is no runtime representation of the type-inferencing or >> checking machinery >> - there is no runtime representation of the evaluation machinery >> - there is no runtime representation of the lexical or parsing >> machinery In fact, Haskell does offer a somewhat similar parallel to macros in Lisp: Template Haskell (see http://www.haskell.org/haskellwiki/Template_Haskell). To continue: >>Op 11-sep-2007, om 18:43 heeft Greg Meredith het volgende geschreven: >> >>[...] >> >>Template Haskell [1] is a system that lets you write programs that get >>executed at *compile time*, and that produce parts of the Haskell program >>to be compiled by manipulating a representation of the program as structured >>data. It's a form of reflection restricted to compile time, if you'd ask me. >> >>[...] >> >>[1] http://www.haskell.org/haskellwiki/Template_Haskell > >According to the site referenced by the above-mentioned link, > >>Template Haskell is an extension to Haskell 98 that allows you to do type-safe >>compile-time meta-programming, with Haskell both as the manipulating language >>and the language being manipulated. There is also a related thread on this issue: Explanation of macros; Haskell macros http://mail.python.org/pipermail/python-list/2003-October/228339.html The above-referenced paper also references the following related paper discussing this topic in more detail: Template Meta-programming for Haskell by Tim Sheard and Simon Peyton Jones http://www.haskell.org/th/papers/meta-haskell.ps >Also, could someone point me to a gentle introduction to syntax, >semantics and type systems? I understand that lisp-like macros do not >exist in Haskell since they would break the type system and could give >rise to unclear semantics. I'd like to understand what's going on, so >pointers to books or tutorials would be highly appreciated. One book that is often mentioned in this context is the following: Types and Programming Languages by Benjamin C. Pierce http://www.cis.upenn.edu/~bcpierce/tapl/ Hope this helps.... -- Benjamin L. Russell -- Benjamin L. Russell / DekuDekuplex at Yahoo dot com http://dekudekuplex.wordpress.com/ Translator/Interpreter / Mobile: +011 81 80-3603-6725 "Furuike ya, kawazu tobikomu mizu no oto." -- Matsuo Basho^ From DekuDekuplex at Yahoo.com Tue Feb 10 05:09:13 2009 From: DekuDekuplex at Yahoo.com (Benjamin L.Russell) Date: Tue Feb 10 04:59:05 2009 Subject: [Haskell-beginners] Re: A Comparison of Haskell and Scheme References: <6qg2p4902o0ufaknthbqccmrs1k4abisps@4ax.com> Message-ID: <6ck2p4l8ckiq8rk5ucap4iv488b6ocvngc@4ax.com> On Tue, 10 Feb 2009 19:03:31 +0900, Benjamin L.Russell wrote: >There is also a related thread on this issue: > >Explanation of macros; Haskell macros >http://mail.python.org/pipermail/python-list/2003-October/228339.html > >The above-referenced paper also references the following related paper >discussing this topic in more detail: > >Template Meta-programming for Haskell >by Tim Sheard and Simon Peyton Jones >http://www.haskell.org/th/papers/meta-haskell.ps Correction: Please substitute "thread" for "paper" in the above-quoted sentence starting with "The above-referenced paper...." Apologies. -- Benjamin L. Russell -- Benjamin L. Russell / DekuDekuplex at Yahoo dot com http://dekudekuplex.wordpress.com/ Translator/Interpreter / Mobile: +011 81 80-3603-6725 "Furuike ya, kawazu tobikomu mizu no oto." -- Matsuo Basho^ From felipe.lessa at gmail.com Tue Feb 10 05:25:55 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Tue Feb 10 05:15:43 2009 Subject: [Haskell-beginners] A Comparison of Haskell and Scheme In-Reply-To: References: Message-ID: On Tue, Feb 10, 2009 at 5:18 AM, Benjamin L. Russell wrote: > Although somewhat dated (posted on October 24, 2006 4:39 PM, to be > precise), here is an interesting comparison of Haskell and Scheme, by > Mark C. Chu-Carroll, a PhD computer scientist who works as a software > engineer at Google, on his blog, regarding whether someone should > translate Douglas Hofstadter's columns introducing Scheme to replace > the Scheme code with Haskell code: He forgot to tell that Haskell is the best imperative language :). > The entry discusses differences in syntax, typing, and semantics, and > makes for interesting reading. Surprisingly, he states that Haskell > syntax is easier to learn for beginners: I don't think that's surprising at all. Haskell's syntax is one of the bests I've ever used: clean, simple, and yet powerful. -- Felipe. From byorgey at seas.upenn.edu Tue Feb 10 10:57:56 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Tue Feb 10 10:47:41 2009 Subject: [Haskell-beginners] Recursive Let In-Reply-To: <200902091743.03601.poliquin@softcomp.com> References: <200902091743.03601.poliquin@softcomp.com> Message-ID: <20090210155756.GA23299@seas.upenn.edu> On Mon, Feb 09, 2009 at 05:43:03PM -0800, Tom Poliquin wrote: > > > 1) How does recursion happen? > > Being an ex-Schemer I recalled that let x = 3 > get translated into something like > > (lambda (x) ... ) 3 > > So now there's a function involved. It's clear that b:d is > > (cons b d) > > another function. So with appropriate plumbing > I could see the thing recurses but the Haskell viewpoint > eludes me. In Haskell, thinking of let expressions as being translated into lambda expressions is not very helpful, precisely because of the special ability to have recursive let bindings. In Haskell it is perfectly OK to have something like let x = 1:y y = 0:x in ... but it is not clear how this would get translated into function application (which would come first?). It's better just to think of let as a special, primitive construct. > > 2) How do things get started? > > It seems that Haskell could figure out that > 'd' is a list. If an uninitialized (undefined?) > list contains [] then things are reasonably > straightforward .. An "uninitialized" list does not contain []. I think perhaps your use of the terms "uninitialized/undefined" might betray an imperative mindset (?); in any case these are not the right words to use, since they give an incorrect picture of what is going on. Here's what actually happens: as a first example, let's consider the let-binding let x = 1:x in ... What happens here is that x is bound to a closure or 'thunk' (suspended computation) which, *when needed*, will evaluate to 1:x. This is laziness at work. x is not 'uninitialized'; it is perfectly well initialized to this thunk. It is definitely not equal to []; at this point the runtime doesn't know anything about x other than the fact that it is a list, and that there is a thunk which may be evaluated if and when the value of x is actually needed. If you don't use x anywhere in the ..., nothing will ever happen and the thunk will eventually get garbage collected (in fact, it's likely that the compiler would optimize x away and it would never be in memory at all). But suppose the value of x is needed (that is, some code pattern-matches on x). Then the thunk will be evaluated just far enough to allow the pattern-match: in particular, x will now be a list with first element 1, and remainder of the list... another thunk. At this point x is not [1]; it is [1:...] where the ... represents another thunk which will evaluate to x. This process repeats as more elements of x are needed, with each thunk evaluating just far enough to allow the necessary pattern-matches, and suspending the remainder of computation in another thunk. Now, let's look at your example: let (c,d) = (d,b:d) Of course, c and d will both be initialized to thunks which will evaluate to lists as needed. It's important to realize that from a semantic point of view, b, c, and d never change. They always represent the same, unchanging values, as defined by this let statement; it's just that operationally, only part of those values may be actually evaluated, as needed. If b has the value 7, then d = 7:d, which means d = 7:7:d, which means d = 7:7:7:d, and so on, and the runtime will expand d out as far as needed (in this case, 10 elements). You really can think of d as *being* an infinite list of 7's, only part of which is evaluated. > This is all fine. The only thing that subconsciously > nags me is that we appear to 'return' each time which > would imply that we would leave the closure causing 'd' > to be undefined again. One way to think about it is that we only 'return' once: when tracePlus 7 is evaluated, it returns, once and for all, a value 'c', the evaluation of which happens to be suspended; it will be evaluated further as needed. Of course, if you want, you can indeed think of execution jumping back and forth between main and tracePlus as c is evaluated bit by bit, but I think this view is unhelpful, as it suggests procedure calls in an imperative language, where local variables such as 'd' would indeed go out of scope each time tracePlus 'exited'. Instead, think of tracePlus as returning a closure, which packages up the values of b, c, and d; it is this closure which is then evaluated incrementally as execution continues. > Back to the undefined list ... if it's *not* an > [] and has something to do with bottom ( _|_ ) > then my eyes glaze over and I have to go watch a > Woody Allen movie to reset. A truly _undefined_ list is indeed _|_, and not []. [] is quite defined; it is the list with no elements. _|_ just means 'the completely undefined value'. However, as I hope I have made clear above, the c and d in your example are neither [] nor undefined, so this is immaterial. There is much more to say on the topic, and doubtless there are places where I've told some small fibs because the truth is more complicated. But hopefully this helps provide a useful way to understand things. -Brent From krewinkel at gmx.net Tue Feb 10 11:32:37 2009 From: krewinkel at gmx.net (Albert Krewinkel) Date: Tue Feb 10 11:22:28 2009 Subject: [Haskell-beginners] Re: A Comparison of Haskell and Scheme In-Reply-To: <6ck2p4l8ckiq8rk5ucap4iv488b6ocvngc@4ax.com> (Benjamin L. Russell's message of "Tue, 10 Feb 2009 19:09:13 +0900") References: <6qg2p4902o0ufaknthbqccmrs1k4abisps@4ax.com> <6ck2p4l8ckiq8rk5ucap4iv488b6ocvngc@4ax.com> Message-ID: Benjamin L.Russell writes: > On Tue, 10 Feb 2009 19:03:31 +0900, Benjamin L.Russell > wrote: > >>There is also a related thread on this issue: >> >>Explanation of macros; Haskell macros >>http://mail.python.org/pipermail/python-list/2003-October/228339.html >> >>The above-referenced paper also references the following related paper >>discussing this topic in more detail: >> >>Template Meta-programming for Haskell >>by Tim Sheard and Simon Peyton Jones >>http://www.haskell.org/th/papers/meta-haskell.ps > > Correction: Please substitute "thread" for "paper" in the > above-quoted sentence starting with "The above-referenced paper...." > > Apologies. > > -- Benjamin L. Russell Those are great resources! Thanks a lot! Albert From poliquin at softcomp.com Wed Feb 11 02:37:14 2009 From: poliquin at softcomp.com (Tom Poliquin) Date: Wed Feb 11 03:04:21 2009 Subject: [Haskell-beginners] Recursive Let In-Reply-To: <20090210155756.GA23299@seas.upenn.edu> References: <200902091743.03601.poliquin@softcomp.com> <20090210155756.GA23299@seas.upenn.edu> Message-ID: <200902102337.14901.poliquin@softcomp.com> On Tuesday 10 February 2009 07:57, Brent Yorgey wrote: > On Mon, Feb 09, 2009 at 05:43:03PM -0800, Tom Poliquin wrote: > tracePlus b = let (c,d) = (d,b:d) > ? ? ? ? ? ? ? in c > main = do > ? ? ?w <- return $ take 10 $ tracePlus 7 > ? ? ?print w > > > 1) How does recursion happen? > In Haskell, thinking of let expressions as being translated into > lambda expressions is not very helpful, precisely because of the > special ability to have recursive let bindings. In Haskell it is > perfectly OK to have something like > > let x = 1:y > y = 0:x > in ... > > but it is not clear how this would get translated into function > application (which would come first?). It's better just to think of > let as a special, primitive construct. Ah, this is what I needed, a mental model that actually fits what's happening. > > 2) How do things get started? > An "uninitialized" list does not contain []. I think perhaps your use > of the terms "uninitialized/undefined" might betray an imperative > mindset (?) I've been doing FP for about 3 years (and imperative for 30) I guess old habits are hard to break :-) I went from Scheme to ML and now Haskell and it seems like every day there's something new for me to try to wrap my head around. (Is category theory next ??!! ... into the rabbit hole .. no pejorative intent) > Here's what actually happens: as a first example, let's consider the > let-binding > > let x = 1:x > in ... > > What happens here is that x is bound to a closure or 'thunk' > (suspended computation) which, *when needed*, will evaluate to 1:x. > This is laziness at work. x is not 'uninitialized'; it is perfectly > well initialized to this thunk. Great point. It seems like laziness is the major part of my misunderstanding. Thinking about thunks will help a lot. > Now, let's look at your example: > > let (c,d) = (d,b:d) > > Of course, c and d will both be initialized to thunks which will > evaluate to lists as needed. It's important to realize that from a > semantic point of view, b, c, and d never change. They always > represent the same, unchanging values, as defined by this let > statement; it's just that operationally, only part of those values may > be actually evaluated, as needed. Ok, this clears things up a lot ! I just need to internalize it. > A truly _undefined_ list is indeed _|_, and not []. > However, as I hope I have made clear > above, the c and d in your example are neither [] nor undefined, so > this is immaterial. Good. I'm not ready for _|_ yet .. :-) > There is much more to say on the topic, and doubtless there are places > where I've told some small fibs because the truth is more > complicated. But hopefully this helps provide a useful way to > understand things. > > -Brent Yes it does, and you're right I'm probably not ready for the 'truth' yet :-) Thanks for the very detailed reply. It was extremely helpful! Tom From byorgey at seas.upenn.edu Wed Feb 11 03:29:24 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Wed Feb 11 03:19:07 2009 Subject: [Haskell-beginners] Recursive Let In-Reply-To: <200902102337.14901.poliquin@softcomp.com> References: <200902091743.03601.poliquin@softcomp.com> <20090210155756.GA23299@seas.upenn.edu> <200902102337.14901.poliquin@softcomp.com> Message-ID: <20090211082924.GA14510@seas.upenn.edu> > > Good. I'm not ready for _|_ yet .. :-) There's actually nothing all that difficult about _|_; it is the value of divergent computations--i.e. infinite recursion which never actually produces any data. We usually also say that anything which results in a run-time error is _|_. For example, each of the following is _|_: undefined error "blarg" let x = x in x let y = y + 1 in y > Thanks for the very detailed reply. It was extremely helpful! Glad to hear it! -Brent From tom.davie at gmail.com Wed Feb 11 03:34:54 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Wed Feb 11 03:24:40 2009 Subject: [Haskell-beginners] Recursive Let In-Reply-To: <20090211082924.GA14510@seas.upenn.edu> References: <200902091743.03601.poliquin@softcomp.com> <20090210155756.GA23299@seas.upenn.edu> <200902102337.14901.poliquin@softcomp.com> <20090211082924.GA14510@seas.upenn.edu> Message-ID: <913DFE73-48FF-4628-9DA5-F63166791ACF@gmail.com> On 11 Feb 2009, at 09:29, Brent Yorgey wrote: >> >> Good. I'm not ready for _|_ yet .. :-) > > There's actually nothing all that difficult about _|_; it is the value > of divergent computations--i.e. infinite recursion which never > actually produces any data. We usually also say that anything which > results in a run-time error is _|_. For example, each of the following > is _|_: > > undefined > error "blarg" > let x = x in x > let y = y + 1 in y Note though that it's not the value of divergent computations, but instead of divergent computations that also never produce any output. For example, this divergent computation is not _|_, because it produces values: ones = 1 : ones More precisely, in haskell bottom is a value in every type which we can give no information about at all. In mathematics, bottom is a value which contains the *least* information of any value in the set, this is true in Haskell also, but also guarenteed by the fact that types are extended to include a special "I know nothing at all" value. Bob From wqeqweuqy at hotmail.com Thu Feb 12 03:44:08 2009 From: wqeqweuqy at hotmail.com (Neal Alexander) Date: Thu Feb 12 03:34:42 2009 Subject: [Haskell-beginners] Deforesting binary tree operations? Message-ID: Is it possible to deforest something like this? data Matrix a = Scalar a | Matrix (Matrix a,Matrix a,Matrix a,Matrix a) (*) (Matrix (a11,a12,a21,a22)) (Matrix (b11,b12,b21,b22)) = Matrix ( (a11 * b11) + (a12 * b21), (a11 * b12) + (a12 * b22), (a21 * b11) + (a22 * b21), (a21 * b12) + (a22 * b22) ) (*) (Scalar a) (Scalar b) = Scalar (a * b) From jan.snajder at fer.hr Thu Feb 12 04:20:32 2009 From: jan.snajder at fer.hr (Jan Snajder) Date: Thu Feb 12 04:10:17 2009 Subject: [Haskell-beginners] permuting a list Message-ID: <1234430432.5888.23.camel@arjuna> Hi! I'm trying to write a list permutation function, and there is in fact a nice explanation of how to do it here: http://sneakymustard.com/2008/12/23/shuffling-in-haskell But for the start I wanted to keep things simple and avoid monad transformers (since I'm not into this yet). Instead, I'd like to write a function of type: > permute :: [a] -> IO [a] and so this is what I did: > permute xs = do > let n = length xs - 1 > arr0 <- newListArray (0, n) xs > arr <- foldM swap arr0 [n..1] > getElems arr > where swap arr n = do > x <- readArray arr n > r <- randomRIO (0, n) > y <- readArray arr r > writeArray arr n y > writeArray arr r x > return arr Unfortunately, what I get is: > permute :: (MArray a1 a IO) => [a] -> IO [a] and so when I try to apply this function: > permute [1,2,3] this is what I get: :1:0: No instance for (MArray a1 t IO) arising from a use of `permute' at :1:0-14 Possible fix: add an instance declaration for (MArray a1 t IO) In the expression: permute [1, 2, 3] In the definition of `it': it = permute [1, 2, 3] How can I fix this? Thanx, jan From tom.davie at gmail.com Thu Feb 12 05:24:25 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Feb 12 05:24:56 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: <1234430432.5888.23.camel@arjuna> References: <1234430432.5888.23.camel@arjuna> Message-ID: On 12 Feb 2009, at 10:20, Jan Snajder wrote: > Hi! > > I'm trying to write a list permutation function, and there is in > fact a > nice explanation of how to do it here: > http://sneakymustard.com/2008/12/23/shuffling-in-haskell > > But for the start I wanted to keep things simple and avoid monad > transformers (since I'm not into this yet). Instead, I'd like to > write a > function of type: > >> permute :: [a] -> IO [a] o.O Why not keep things simple and just write a pure function? permute :: [a] -> [[a]] permute xs = [s:ps | (s,ss) <- select xs, ps <- permute ss] select :: [a] -> [(a,[a])] select [] = [] select (x:xs) = (x,xs) : [(s,x:ss) | (s,ss) <- select xs] Bob From patrick.leboutillier at gmail.com Thu Feb 12 09:53:43 2009 From: patrick.leboutillier at gmail.com (Patrick LeBoutillier) Date: Thu Feb 12 09:43:22 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: References: <1234430432.5888.23.camel@arjuna> Message-ID: Hi, > > Why not keep things simple and just write a pure function? > > permute :: [a] -> [[a]] > permute xs = [s:ps | (s,ss) <- select xs, ps <- permute ss] > > select :: [a] -> [(a,[a])] > select [] = [] > select (x:xs) = (x,xs) : [(s,x:ss) | (s,ss) <- select xs] When I run this in ghci I always get an empty list: [patrickl@fc9i386 haskell]$ ghci permute.hs GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Loading package base ... linking ... done. [1 of 1] Compiling Main ( permute.hs, interpreted ) Ok, modules loaded: Main. *Main> permute [1,2,3] [] Am i missing something? Patrick > > Bob > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -- ===================== Patrick LeBoutillier Rosem?re, Qu?bec, Canada From alexander.dunlap at gmail.com Thu Feb 12 10:00:34 2009 From: alexander.dunlap at gmail.com (Alexander Dunlap) Date: Thu Feb 12 09:50:16 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: <1234430432.5888.23.camel@arjuna> References: <1234430432.5888.23.camel@arjuna> Message-ID: <57526e770902120700s658b5cd8qbff96db4ae264496@mail.gmail.com> On Thu, Feb 12, 2009 at 1:20 AM, Jan Snajder wrote: > Hi! > > I'm trying to write a list permutation function, and there is in fact a > nice explanation of how to do it here: > http://sneakymustard.com/2008/12/23/shuffling-in-haskell > > But for the start I wanted to keep things simple and avoid monad > transformers (since I'm not into this yet). Instead, I'd like to write a > function of type: > >> permute :: [a] -> IO [a] > > and so this is what I did: > >> permute xs = do >> let n = length xs - 1 >> arr0 <- newListArray (0, n) xs >> arr <- foldM swap arr0 [n..1] >> getElems arr >> where swap arr n = do >> x <- readArray arr n >> r <- randomRIO (0, n) >> y <- readArray arr r >> writeArray arr n y >> writeArray arr r x >> return arr > > Unfortunately, what I get is: > >> permute :: (MArray a1 a IO) => [a] -> IO [a] > > and so when I try to apply this function: > >> permute [1,2,3] > > this is what I get: > > :1:0: > No instance for (MArray a1 t IO) > arising from a use of `permute' at :1:0-14 > Possible fix: add an instance declaration for (MArray a1 t IO) > In the expression: permute [1, 2, 3] > In the definition of `it': it = permute [1, 2, 3] > > How can I fix this? > > Thanx, > jan > > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > The simplest way to do this is to use base v4, which I believe contains a "permutations" function in Data.List. Alex From apfelmus at quantentunnel.de Thu Feb 12 10:11:23 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Thu Feb 12 10:00:22 2009 Subject: [Haskell-beginners] Re: permuting a list In-Reply-To: References: <1234430432.5888.23.camel@arjuna> Message-ID: Patrick LeBoutillier wrote: >> >> permute :: [a] -> [[a]] >> permute xs = [s:ps | (s,ss) <- select xs, ps <- permute ss] >> >> select :: [a] -> [(a,[a])] >> select [] = [] >> select (x:xs) = (x,xs) : [(s,x:ss) | (s,ss) <- select xs] > > When I run this in ghci I always get an empty list: > > [patrickl@fc9i386 haskell]$ ghci permute.hs > GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help > Loading package base ... linking ... done. > [1 of 1] Compiling Main ( permute.hs, interpreted ) > Ok, modules loaded: Main. > *Main> permute [1,2,3] > [] > > > Am i missing something? No. The base case permute [] = [[]] was missing. Regards, apfelmus -- http://apfelmus.nfshost.com From alan.cameron at iname.com Thu Feb 12 10:19:40 2009 From: alan.cameron at iname.com (Alan Cameron) Date: Thu Feb 12 10:09:07 2009 Subject: [Haskell-beginners] Help with RWH exercises wanted Message-ID: I am baffled by what the correct solution to the exercises in Recursive type section of Chapter 3 should be. 1. Write the converse of fromList for the List type: a function that takes a List a and generates a [a]. 2. Define a tree type that has only one constructor, like our Java example. Instead of the Empty constructor, use the Maybe type to refer to a node's children. fromList is defined in listADT.hs thus -- file: ch03/ListADT.hs fromList (x:xs) = Cons x (fromList xs) fromList [] = Nil Tree is defined in Tree.hs thus -- file: ch03/Tree.hs data Tree a = Node a (Tree a) (Tree a) | Empty deriving (Show) At this point in the book I fail to find any previous examples which might lead me to my own solution and there are no "Answers to Exercises" as far as I can see. I have a feeling that this might be a fundamental piece of knowledge to assist me in further reading of the book. Alan Cameron From daniel.is.fischer at web.de Thu Feb 12 10:38:19 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Feb 12 10:25:20 2009 Subject: [Haskell-beginners] Help with RWH exercises wanted In-Reply-To: References: Message-ID: <200902121638.19848.daniel.is.fischer@web.de> Am Donnerstag, 12. Februar 2009 16:19 schrieb Alan Cameron: > I am baffled by what the correct solution to the exercises in Recursive > type section of Chapter 3 should be. > > 1. Write the converse of fromList for the List type: a function that takes > a List a and generates a [a]. Follow the example of fromList, pattern match on the constructors of the List type and specify for each case what to do (there's only one sensible choice) toList (Cons x xs) = ... toList Nil = ... > > 2. Define a tree type that has only one constructor, like our Java example. > Instead of the Empty constructor, use the Maybe type to refer to a node's > children. > You know the Maybe type: data Maybe a = Nothing | Just a , don't you? If the Java example is what I expect it to be, you just replace the null reference with Nothing and a non-null subtree with (Just subtree). > > fromList is defined in listADT.hs thus > > -- file: ch03/ListADT.hs > fromList (x:xs) = Cons x (fromList xs) > fromList [] = Nil > > Tree is defined in Tree.hs thus > > -- file: ch03/Tree.hs > data Tree a = Node a (Tree a) (Tree a) > > | Empty > > deriving (Show) > > At this point in the book I fail to find any previous examples which might > lead me to my own solution and there are no "Answers to Exercises" as far > as I can see. I have a feeling that this might be a fundamental piece of > knowledge to assist me in further reading of the book. > > Alan Cameron I hope the above hints help you find the solutions yourself, if not, I could go into more detail. Cheers, Daniel From byorgey at seas.upenn.edu Thu Feb 12 11:53:14 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Thu Feb 12 11:42:53 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: <1234430432.5888.23.camel@arjuna> References: <1234430432.5888.23.camel@arjuna> Message-ID: <20090212165314.GA2699@seas.upenn.edu> On Thu, Feb 12, 2009 at 10:20:32AM +0100, Jan Snajder wrote: > > this is what I get: > > :1:0: > No instance for (MArray a1 t IO) > arising from a use of `permute' at :1:0-14 > Possible fix: add an instance declaration for (MArray a1 t IO) > In the expression: permute [1, 2, 3] > In the definition of `it': it = permute [1, 2, 3] > > How can I fix this? > It seems everyone has just been reading the first few words of Jan's email and not the actual content. Jan is clearly trying to write a *random list shuffling* function, not a function to generate permutations. Let's try to be helpful, people... Jan, this is tricky. The type of permute is indeed (MArray a1 a IO) => [a] -> IO [a], but this is fine, it just means that there has to be some sort of mutable array which can store the things you are trying to shuffle. This is not the problem. The problem seems to be that Haskell has no way to know what sort of array you want to use. I was able to get the code to work, but it's sort of sneaky: > {-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-} > import Data.Array.MArray > import Data.Array.IO > import Control.Monad > import System.Random > permute :: forall a. (MArray IOArray a IO) => [a] -> IO [a] > permute xs = do > let n = length xs - 1 > arr0 <- (newListArray (0, n) xs :: IO (IOArray Int a)) > arr <- foldM swap arr0 [n..1] > getElems arr > where swap arr n = do > x <- readArray arr n > r <- randomRIO (0, n) > y <- readArray arr r > writeArray arr n y > writeArray arr r x > return arr We have to give an explicit type annotation on the newListArray, to tell Haskell what kind of array we want to use. But then we also need to use the ScopedTypeVariables extension, so that the 'a' in the type signature for permute scopes over the definition, so that Haskell knows we want the 'a' in the IOArray Int a to be the same type as the 'a' in the type signature. Otherwise it doesn't know they are the same and complains. Also, when I try running permute, it seems to be the identity function, but I guess that's a separate issue! -Brent From wagner.andrew at gmail.com Thu Feb 12 11:58:21 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Thu Feb 12 11:48:00 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: <20090212165314.GA2699@seas.upenn.edu> References: <1234430432.5888.23.camel@arjuna> <20090212165314.GA2699@seas.upenn.edu> Message-ID: > > > It seems everyone has just been reading the first few words of Jan's > email and not the actual content. Jan is clearly trying to write a > *random list shuffling* function, not a function to generate > permutations. Let's try to be helpful, people... > > Agreed, I've been quite confused by this thread. In the spirit of laziness, though, wouldn't it seem like the "right" method is to generate all the permutations lazily, and then choose a random element of that list? -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090212/f236ad73/attachment.htm From daniel.is.fischer at web.de Thu Feb 12 13:20:27 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Feb 12 13:07:31 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: <20090212165314.GA2699@seas.upenn.edu> References: <1234430432.5888.23.camel@arjuna> <20090212165314.GA2699@seas.upenn.edu> Message-ID: <200902121920.27150.daniel.is.fischer@web.de> Am Donnerstag, 12. Februar 2009 17:53 schrieb Brent Yorgey: > On Thu, Feb 12, 2009 at 10:20:32AM +0100, Jan Snajder wrote: > > this is what I get: > > > > :1:0: > > No instance for (MArray a1 t IO) > > arising from a use of `permute' at :1:0-14 > > Possible fix: add an instance declaration for (MArray a1 t IO) > > In the expression: permute [1, 2, 3] > > In the definition of `it': it = permute [1, 2, 3] > > > > How can I fix this? > > > It seems everyone has just been reading the first few words of Jan's > email and not the actual content. Jan is clearly trying to write a > *random list shuffling* function, not a function to generate > permutations. Let's try to be helpful, people... > > > Jan, this is tricky. The type of permute is indeed (MArray a1 a IO) > => [a] -> IO [a], but this is fine, it just means that there has to be > some sort of mutable array which can store the things you are trying > to shuffle. This is not the problem. The problem seems to be that > Haskell has no way to know what sort of array you want to use. I was > > able to get the code to work, but it's sort of sneaky: > > {-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-} > > > > import Data.Array.MArray > > import Data.Array.IO > > import Control.Monad > > import System.Random > > > > permute :: forall a. (MArray IOArray a IO) => [a] -> IO [a] > > permute xs = do > > let n = length xs - 1 > > arr0 <- (newListArray (0, n) xs :: IO (IOArray Int a)) > > arr <- foldM swap arr0 [n..1] > > getElems arr > > where swap arr n = do > > x <- readArray arr n > > r <- randomRIO (0, n) > > y <- readArray arr r > > writeArray arr n y > > writeArray arr r x > > return arr > > We have to give an explicit type annotation on the newListArray, to > tell Haskell what kind of array we want to use. But then we also need > to use the ScopedTypeVariables extension, so that the 'a' in the type > signature for permute scopes over the definition, so that Haskell > knows we want the 'a' in the IOArray Int a to be the same type as the > 'a' in the type signature. Otherwise it doesn't know they are the > same and complains. > > Also, when I try running permute, it seems to be the identity > function, but I guess that's a separate issue! > That's because [n .. 1] is almost always an empty list. That code changes only lists of length 2. Make it foldM swap arr0 [n, n-1 .. 1] and it works. *Main> permute [1 .. 5] [3,2,1,5,4] > -Brent From byorgey at seas.upenn.edu Thu Feb 12 13:33:29 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Thu Feb 12 13:23:08 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: References: <1234430432.5888.23.camel@arjuna> <20090212165314.GA2699@seas.upenn.edu> Message-ID: <20090212183329.GA2931@seas.upenn.edu> On Thu, Feb 12, 2009 at 11:58:21AM -0500, Andrew Wagner wrote: > > > > > > It seems everyone has just been reading the first few words of Jan's > > email and not the actual content. Jan is clearly trying to write a > > *random list shuffling* function, not a function to generate > > permutations. Let's try to be helpful, people... > > > > > > Agreed, I've been quite confused by this thread. In the spirit of laziness, > though, wouldn't it seem like the "right" method is to generate all the > permutations lazily, and then choose a random element of that list? Well, it sounds nice, but it's pretty inefficient. And by "pretty inefficient" I mean "horrendously, terribly inefficient" -- there are n! permutations of a list of length n, so this would take time O(n!) as opposed to O(n); O(n!) is even worse than O(2^n). -Brent From wagner.andrew at gmail.com Thu Feb 12 13:45:22 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Thu Feb 12 13:35:01 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: <20090212183329.GA2931@seas.upenn.edu> References: <1234430432.5888.23.camel@arjuna> <20090212165314.GA2699@seas.upenn.edu> <20090212183329.GA2931@seas.upenn.edu> Message-ID: Hrmm, I suppose you're right. I was thinking that we could magically write permute so that it wound up with n! thunks in an array, and then grab the nth element in constant time. I guess that's not very correct. And by "not very" I mean "not even close to". On Thu, Feb 12, 2009 at 1:33 PM, Brent Yorgey wrote: > Well, it sounds nice, but it's pretty inefficient. And by "pretty > inefficient" I mean "horrendously, terribly inefficient" -- there are > n! permutations of a list of length n, so this would take time O(n!) > as opposed to O(n); O(n!) is even worse than O(2^n). > > -Brent > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090212/8dc5f5ec/attachment-0001.htm From tom.davie at gmail.com Thu Feb 12 14:19:46 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Feb 12 14:09:28 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: <20090212183329.GA2931@seas.upenn.edu> References: <1234430432.5888.23.camel@arjuna> <20090212165314.GA2699@seas.upenn.edu> <20090212183329.GA2931@seas.upenn.edu> Message-ID: <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> On 12 Feb 2009, at 19:33, Brent Yorgey wrote: > On Thu, Feb 12, 2009 at 11:58:21AM -0500, Andrew Wagner wrote: >>> >>> >>> It seems everyone has just been reading the first few words of Jan's >>> email and not the actual content. Jan is clearly trying to write a >>> *random list shuffling* function, not a function to generate >>> permutations. Let's try to be helpful, people... >>> >>> >> >> Agreed, I've been quite confused by this thread. In the spirit of >> laziness, >> though, wouldn't it seem like the "right" method is to generate all >> the >> permutations lazily, and then choose a random element of that list? > > Well, it sounds nice, but it's pretty inefficient. And by "pretty > inefficient" I mean "horrendously, terribly inefficient" -- there are > n! permutations of a list of length n, so this would take time O(n!) > as opposed to O(n); O(n!) is even worse than O(2^n). Would it? We're talking about lazyness here... it's not gonna compute one it doesn't need, and if you're somewhat cleverer with your permute function than I was, I'm sure you can do as little computation as the imperative version. Bob From byorgey at seas.upenn.edu Thu Feb 12 14:40:09 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Thu Feb 12 14:29:48 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> References: <1234430432.5888.23.camel@arjuna> <20090212165314.GA2699@seas.upenn.edu> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> Message-ID: <20090212194009.GA3897@seas.upenn.edu> On Thu, Feb 12, 2009 at 08:19:46PM +0100, Thomas Davie wrote: > > On 12 Feb 2009, at 19:33, Brent Yorgey wrote: > >> On Thu, Feb 12, 2009 at 11:58:21AM -0500, Andrew Wagner wrote: >>>> >>>> >>>> It seems everyone has just been reading the first few words of Jan's >>>> email and not the actual content. Jan is clearly trying to write a >>>> *random list shuffling* function, not a function to generate >>>> permutations. Let's try to be helpful, people... >>>> >>>> >>> >>> Agreed, I've been quite confused by this thread. In the spirit of >>> laziness, >>> though, wouldn't it seem like the "right" method is to generate all the >>> permutations lazily, and then choose a random element of that list? >> >> Well, it sounds nice, but it's pretty inefficient. And by "pretty >> inefficient" I mean "horrendously, terribly inefficient" -- there are >> n! permutations of a list of length n, so this would take time O(n!) >> as opposed to O(n); O(n!) is even worse than O(2^n). > > Would it? We're talking about lazyness here... it's not gonna compute one > it doesn't need, and if you're somewhat cleverer with your permute function > than I was, I'm sure you can do as little computation as the imperative > version. Indexing into a list is still O(n) in the index, whether you actually compute the elements or not. That is, if you're actually building a list of permutations, then even if you don't compute anything about the permutations you don't need, just traversing through the spine of the list to get the one you want will take a very long time---O(n!)---for reasonably large n. However, you can actually write a pure function with type Int -> [a] -> [a] which just computes which permutation "would be" at the given index, without ever actually constructing a list of them. I'll leave this as an interesting exercise (hint: convert the input number to "base factorial"...), although I still think it's not going to be quite as fast as the imperative version (at least O(n lg n)). -Brent From daniel.is.fischer at web.de Thu Feb 12 14:46:22 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Feb 12 14:36:07 2009 Subject: [Haskell-beginners] permuting a list In-Reply-To: <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> References: <1234430432.5888.23.camel@arjuna> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> Message-ID: <200902122046.22430.daniel.is.fischer@web.de> Am Donnerstag, 12. Februar 2009 20:19 schrieb Thomas Davie: > On 12 Feb 2009, at 19:33, Brent Yorgey wrote: > > On Thu, Feb 12, 2009 at 11:58:21AM -0500, Andrew Wagner wrote: > >>> > >>> It seems everyone has just been reading the first few words of Jan's > >>> email and not the actual content. Jan is clearly trying to write a > >>> *random list shuffling* function, not a function to generate > >>> permutations. Let's try to be helpful, people... > >>> > >> > >> Agreed, I've been quite confused by this thread. In the spirit of > >> laziness, > >> though, wouldn't it seem like the "right" method is to generate all > >> the > >> permutations lazily, and then choose a random element of that list? > > > > Well, it sounds nice, but it's pretty inefficient. And by "pretty > > inefficient" I mean "horrendously, terribly inefficient" -- there are > > n! permutations of a list of length n, so this would take time O(n!) > > as opposed to O(n); O(n!) is even worse than O(2^n). > > Would it? We're talking about lazyness here... it's not gonna compute > one it doesn't need, and if you're somewhat cleverer with your permute > function than I was, I'm sure you can do as little computation as the > imperative version. > > Bob But to find the k-th permutation, it would have to traverse k cons cells containing thunks, wouldn't it? Well, the following is O(n^2), not quite O(n), but at least it's not "horrendously, terribly inefficient". module Permutations where import Data.List (sortBy, genericSplitAt, genericLength) import Data.Ord (comparing) factorialDigits :: Integer -> [Integer] factorialDigits k = go k 2 where go 0 _ = [] go m d = case m `divMod` d of (q,r) -> r:go q (d+1) permIndices :: Integer -> [Integer] permIndices k = go [0] 1 fds where fds = factorialDigits k go acc d [] = acc ++ [d .. ] go acc d (p:ps) = case genericSplitAt (d-p) acc of (front,back) -> go (front ++ d:back) (d+1) ps kthPerm :: Integer -> [a] -> [a] kthPerm k = map snd . sortBy (comparing fst) . zip (permIndices k) From alan.cameron at iname.com Thu Feb 12 15:39:56 2009 From: alan.cameron at iname.com (Alan Cameron) Date: Thu Feb 12 15:29:35 2009 Subject: [Haskell-beginners] A possibly foolish question Message-ID: Is it possible to have a Haskell function or functions included in a C++ program's structure and used as a procedure? Alan Cameron From tom.davie at gmail.com Thu Feb 12 17:53:49 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Feb 12 17:43:43 2009 Subject: [Haskell-beginners] A possibly foolish question In-Reply-To: References: Message-ID: <9BBE17FF-24E3-4F6A-B02E-4433FFB47A4E@gmail.com> On 12 Feb 2009, at 21:39, Alan Cameron wrote: > Is it possible to have a Haskell function or functions included in a > C++ > program's structure and used as a procedure? Yes, see the FFI (or Foreign Function Interface) documentation. That'll let you export Haskell functions into C land, and from there to C++. Bob From KMARTINE at altera.com Thu Feb 12 18:36:50 2009 From: KMARTINE at altera.com (Kirk Martinez) Date: Thu Feb 12 21:08:16 2009 Subject: [Haskell-beginners] cabal-install can't connect In-Reply-To: <5a376f550902082259l5c21219encd8c1e7d02c21364@mail.gmail.com> Message-ID: Thanks, Salvatore. I was able to get cabal install working by setting IE to use a local proxy server which is set up to cascade through to my corporate proxy. I was already using CCproxy for testing some other proxy stuff internally, so that's what I used. It works great! I only use IE for those proxy settings now, and Firefox for my day to day browsing needs. Thanks a bunch, Kirk -----Original Message----- From: Salvatore Insalaco [mailto:kirby81@gmail.com] Sent: Sunday, February 08, 2009 10:59 PM To: Kirk Martinez Cc: beginners@haskell.org Subject: Re: [Haskell-beginners] cabal-install can't connect On Fri, Feb 6, 2009 at 7:25 PM, Kirk Martinez wrote: > I'm trying to use cabal-install through the firewall at my work and I am > consistently denied: In my experience, cabal-install ignores the http_proxy variable on Windows, and uses the Internet Explorer proxy registry key. Another problem could be that your proxy is using NTLM authentication, that cabal doesn't support. To solve this problem, if your proxy supports BASIC authentication, just put the proxy informations in the Internet Explorer proxy dialog; you have to do it even if there's the "automatic proxy configuration" setting, as cabal is unable to use it. If your proxy supports NTLM authentication, just download a package like http://www.geocities.com/rozmanov/ntlm/ and then put its host and port as proxy in Internet Explorer. Salvatore Confidentiality Notice. This message may contain information that is confidential or otherwise protected from disclosure. If you are not the intended recipient, you are hereby notified that any use, disclosure, dissemination, distribution, or copying of this message, or any attachments, is strictly prohibited. If you have received this message in error, please advise the sender by reply e-mail, and delete the message and any attachments. Thank you. From jan.snajder at fer.hr Fri Feb 13 04:23:33 2009 From: jan.snajder at fer.hr (Jan Snajder) Date: Fri Feb 13 04:13:17 2009 Subject: [Haskell-beginners] Re: permuting a list Message-ID: <1234517013.5888.40.camel@arjuna> Brent Yorgey wrote: > It seems everyone has just been reading the first few words of Jan's > email and not the actual content. Jan is clearly trying to write a > *random list shuffling* function, not a function to generate > permutations. Let's try to be helpful, people... > Thanks Brant, I forgot to mention explicitly that I need a random permutation. > Jan, this is tricky. The type of permute is indeed (MArray a1 a IO) > => [a] -> IO [a], but this is fine, it just means that there has to be > some sort of mutable array which can store the things you are trying > to shuffle. > This is not the problem. The problem seems to be that > Haskell has no way to know what sort of array you want to use. I was > able to get the code to work, but it's sort of sneaky: > > > {-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-} I guess by 'sneaky' you mean this solution is GHC-specific? > > import Data.Array.MArray > > import Data.Array.IO > > import Control.Monad > > import System.Random > > > permute :: forall a. (MArray IOArray a IO) => [a] -> IO [a] > > permute xs = do > > let n = length xs - 1 > > arr0 <- (newListArray (0, n) xs :: IO (IOArray Int a)) > > arr <- foldM swap arr0 [n..1] > > getElems arr > > where swap arr n = do > > x <- readArray arr n > > r <- randomRIO (0, n) > > y <- readArray arr r > > writeArray arr n y > > writeArray arr r x > > return arr Ok, this seems to work! (after replacing '[n..1]' with [n,n-1,..1] as Daniel noted). Great! Why do I need 'forall a' ? Aren't type variables implicitly universaly quantified? j. From felipe.lessa at gmail.com Fri Feb 13 04:29:48 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Fri Feb 13 04:19:29 2009 Subject: [Haskell-beginners] Re: permuting a list In-Reply-To: <1234517013.5888.40.camel@arjuna> References: <1234517013.5888.40.camel@arjuna> Message-ID: On Fri, Feb 13, 2009 at 7:23 AM, Jan Snajder wrote: > Why do I need 'forall a' ? Aren't type variables implicitly universaly > quantified? You don't need it, it's just a matter of style. Some prefer to make it explicit, others not. I think it is only useful when you have lots of existentials nearby. -- Felipe. From daniel.is.fischer at web.de Fri Feb 13 04:56:16 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Fri Feb 13 04:43:17 2009 Subject: [Haskell-beginners] Re: permuting a list In-Reply-To: <1234517013.5888.40.camel@arjuna> References: <1234517013.5888.40.camel@arjuna> Message-ID: <200902131056.16306.daniel.is.fischer@web.de> Am Freitag, 13. Februar 2009 10:23 schrieb Jan Snajder: > Brent Yorgey wrote: > > It seems everyone has just been reading the first few words of Jan's > > email and not the actual content. Jan is clearly trying to write a > > *random list shuffling* function, not a function to generate > > permutations. Let's try to be helpful, people... > > > > Thanks Brant, I forgot to mention explicitly that I need a random > permutation. > > > Jan, this is tricky. The type of permute is indeed (MArray a1 a IO) > > => [a] -> IO [a], but this is fine, it just means that there has to be > > some sort of mutable array which can store the things you are trying > > to shuffle. > > This is not the problem. The problem seems to be that > > Haskell has no way to know what sort of array you want to use. I was > > > > able to get the code to work, but it's sort of sneaky: > > > {-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-} > > I guess by 'sneaky' you mean this solution is GHC-specific? > > > > import Data.Array.MArray > > > import Data.Array.IO > > > import Control.Monad > > > import System.Random > > > > > > permute :: forall a. (MArray IOArray a IO) => [a] -> IO [a] > > > permute xs = do > > > let n = length xs - 1 > > > arr0 <- (newListArray (0, n) xs :: IO (IOArray Int a)) > > > arr <- foldM swap arr0 [n..1] > > > getElems arr > > > where swap arr n = do > > > x <- readArray arr n > > > r <- randomRIO (0, n) > > > y <- readArray arr r > > > writeArray arr n y > > > writeArray arr r x > > > return arr > > Ok, this seems to work! (after replacing '[n..1]' with [n,n-1,..1] as > Daniel noted). Great! > > Why do I need 'forall a' ? Aren't type variables implicitly universaly > quantified? You need the forall a to bring the type variable a into scope. Without it, the a in arr0 <- (newListArray (0, n) xs :: IO (IOArray Int a)) would be implicitly universally quantified, too, and you would say that all elements of xs had type (forall b. b), which means all are _|_. Having brought the a from permute's type signature into scope, the a in the above line is the *same* a as the one in permute's type signature. > > j. Cheers, Daniel From felipe.lessa at gmail.com Fri Feb 13 05:03:27 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Fri Feb 13 04:53:04 2009 Subject: [Haskell-beginners] Re: permuting a list In-Reply-To: <200902131056.16306.daniel.is.fischer@web.de> References: <1234517013.5888.40.camel@arjuna> <200902131056.16306.daniel.is.fischer@web.de> Message-ID: On Fri, Feb 13, 2009 at 7:56 AM, Daniel Fischer wrote: > You need the forall a to bring the type variable a into scope. Without it, the > a in > > arr0 <- (newListArray (0, n) xs :: IO (IOArray Int a)) > > would be implicitly universally quantified, too, and you would say that all > elements of xs had type (forall b. b), which means all are _|_. > Having brought the a from permute's type signature into scope, the a in the > above line is the *same* a as the one in permute's type signature. Whoops, sorry about that, didn't see that ScopedTypeVariables was active. :) -- Felipe. From apfelmus at quantentunnel.de Fri Feb 13 05:25:04 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Fri Feb 13 05:14:00 2009 Subject: [Haskell-beginners] Re: permuting a list In-Reply-To: <1234517013.5888.40.camel@arjuna> References: <1234517013.5888.40.camel@arjuna> Message-ID: Jan Snajder wrote: > Brent Yorgey wrote: > >> The problem seems to be that >> Haskell has no way to know what sort of array you want to use. I was >> able to get the code to work, but it's sort of sneaky: >> >>> {-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-} >>> >>> import Data.Array.MArray >>> import Data.Array.IO >>> import Control.Monad >>> import System.Random >>> permute :: forall a. (MArray IOArray a IO) => [a] -> IO [a] >>> permute xs = do >>> let n = length xs - 1 >>> arr0 <- (newListArray (0, n) xs :: IO (IOArray Int a)) >>> arr <- foldM swap arr0 [n..1] >>> getElems arr >>> where swap arr n = do >>> x <- readArray arr n >>> r <- randomRIO (0, n) >>> y <- readArray arr r >>> writeArray arr n y >>> writeArray arr r x >>> return arr The type class constraint is not needed because IOArray can hold any element type anyway. (It's unboxed arrays that only work for certain element types). Thus, you can write FlexibleConstraints extension and simply write permute :: forall a. [a] -> IO [a] instead. Also, I think that specifying the type of arr0 as (arr0 :: IOArray Int a) <- newListArray (0, n) xs should work as well. -- http://apfelmus.nfshost.com From daniel.is.fischer at web.de Fri Feb 13 05:30:34 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Fri Feb 13 05:17:32 2009 Subject: [Haskell-beginners] Re: permuting a list In-Reply-To: <1234517013.5888.40.camel@arjuna> References: <1234517013.5888.40.camel@arjuna> Message-ID: <200902131130.34556.daniel.is.fischer@web.de> Am Freitag, 13. Februar 2009 10:23 schrieb Jan Snajder: > Brent Yorgey wrote: > > It seems everyone has just been reading the first few words of Jan's > > email and not the actual content. Jan is clearly trying to write a > > *random list shuffling* function, not a function to generate > > permutations. Let's try to be helpful, people... > > > > Thanks Brant, I forgot to mention explicitly that I need a random > permutation. > > > Jan, this is tricky. The type of permute is indeed (MArray a1 a IO) > > => [a] -> IO [a], but this is fine, it just means that there has to be > > some sort of mutable array which can store the things you are trying > > to shuffle. > > This is not the problem. The problem seems to be that > > Haskell has no way to know what sort of array you want to use. I was > > > > able to get the code to work, but it's sort of sneaky: > > > {-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-} > > I guess by 'sneaky' you mean this solution is GHC-specific? It can be made a little less sneaky, you don't need FlexibleContexts, because the type signature permute :: forall a. [a] -> IO [a] works, too (code otherwise unchanged). But that still doesn't work with hugs :( However, if you bring the array-creation to top level, it doesn't need any module-specific language extensions: module Perms where import Data.Array.MArray import Data.Array.IO import Control.Monad import System.Random -- call with toArray (length xs - 1) xs toArray :: Int -> [a] -> IO (IOArray Int a) toArray n xs = newListArray (0,n) xs permute :: [a] -> IO [a] permute xs = do let n = length xs - 1 arr0 <- toArray n xs arr <- foldM swap arr0 [n, n-1 .. 1] getElems arr where swap arr n = do x <- readArray arr n r <- randomRIO (0, n) y <- readArray arr r writeArray arr n y writeArray arr r x return arr and it works in hugs, too (needs the -98 flag, because one of the imports needs ST.hs, which has foralled type signatures). Cheers, Daniel From apfelmus at quantentunnel.de Sat Feb 14 10:37:44 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Sat Feb 14 10:26:41 2009 Subject: [Haskell-beginners] Re: permuting a list In-Reply-To: <200902122046.22430.daniel.is.fischer@web.de> References: <1234430432.5888.23.camel@arjuna> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> <200902122046.22430.daniel.is.fischer@web.de> Message-ID: Daniel Fischer wrote: > Thomas Davie wrote: >> Brent Yorgey wrote: >>> Andrew Wagner wrote: >>>> Brent Yorgey wrote >>>>> It seems everyone has just been reading the first few >>>>> words of Jan's email and not the actual content. Jan is >>>>> clearly trying to write a *random list shuffling* function, >>>>> not a function to generate permutations. Let's try to be >>>>> helpful, people... >>>> >>>> Agreed, I've been quite confused by this thread. In the spirit >>>> of laziness, though, wouldn't it seem like the "right" method >>>> is to generate all the permutations lazily, and then choose a >>>> random element of that list? >>> >>> Well, it sounds nice, but it's pretty inefficient. And by >>> "pretty inefficient" I mean "horrendously, terribly inefficient" >>> -- there are n! permutations of a list of length n, so this would >>> take time O(n!) as opposed to O(n); O(n!) is even worse than >>> O(2^n). >> >> Would it? We're talking about lazyness here... it's not gonna >> compute one it doesn't need, and if you're somewhat cleverer with >> your permute function than I was, I'm sure you can do as little >> computation as the imperative version. > > But to find the k-th permutation, it would have to traverse k cons > cells containing thunks, wouldn't it? > > Well, the following is O(n^2), not quite O(n), but at least it's not > "horrendously, terribly inefficient". That of course begs the question whether there is a faster but purely functional algorithm for generating random permutations without indexes and arrays? The answer is a resounding "yes" and the main idea is that shuffling a list is *essentially the same* as sorting a list; the minor difference being that the former chooses a permutation at random while the latter chooses a very particular permutation, namely the one that sorts the input. For the full exposition, see http://apfelmus.nfshost.com/random-permutations.html Regards, apfelmus -- http://apfelmus.nfshost.com From daniel.is.fischer at web.de Sat Feb 14 11:46:52 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sat Feb 14 11:33:47 2009 Subject: [Haskell-beginners] Re: permuting a list In-Reply-To: References: <1234430432.5888.23.camel@arjuna> <200902122046.22430.daniel.is.fischer@web.de> Message-ID: <200902141746.52960.daniel.is.fischer@web.de> Am Samstag, 14. Februar 2009 16:37 schrieb Heinrich Apfelmus: > > That of course begs the question whether there is a faster but purely No, it didn't beg any question. (Sorry for being a humourless pedant here) > functional algorithm for generating random permutations without indexes > and arrays? > > The answer is a resounding "yes" and the main idea is that shuffling a > list is *essentially the same* as sorting a list; the minor difference > being that the former chooses a permutation at random while the latter > chooses a very particular permutation, namely the one that sorts the input. > > For the full exposition, see > > http://apfelmus.nfshost.com/random-permutations.html Excellent work, thanks. > > > Regards, > apfelmus Cheers, Daniel From jon.fairbairn at cl.cam.ac.uk Sun Feb 15 06:10:28 2009 From: jon.fairbairn at cl.cam.ac.uk (Jon Fairbairn) Date: Sun Feb 15 06:04:32 2009 Subject: [Haskell-beginners] Re: permuting a list References: <1234430432.5888.23.camel@arjuna> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> <200902122046.22430.daniel.is.fischer@web.de> Message-ID: Heinrich Apfelmus writes: > The answer is a resounding "yes" and the main idea is that shuffling a > list is *essentially the same* as sorting a list; the minor difference > being that the former chooses a permutation at random while the latter > chooses a very particular permutation, namely the one that sorts the input. > > For the full exposition, see > > http://apfelmus.nfshost.com/random-permutations.html I haven't been following the thread, but my initial reaction would have been something like use System.Random.randoms to get a list rs and then do (roughly) randomPerm = map snd . sortBy (compare `on` fst) . zip rs How bad is that? I mean, how unfair does it get? -- J?n Fairbairn Jon.Fairbairn@cl.cam.ac.uk http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2009-01-31) From aruiz at um.es Sun Feb 15 07:22:51 2009 From: aruiz at um.es (Alberto Ruiz) Date: Sun Feb 15 07:12:26 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Re: permuting a list In-Reply-To: References: <1234430432.5888.23.camel@arjuna> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> <200902122046.22430.daniel.is.fischer@web.de> Message-ID: <4998091B.2030403@um.es> Heinrich Apfelmus wrote: > Jon Fairbairn wrote: >> Heinrich Apfelmus writes: >> >>> The answer is a resounding "yes" and the main idea is that shuffling a >>> list is *essentially the same* as sorting a list; the minor difference >>> being that the former chooses a permutation at random while the latter >>> chooses a very particular permutation, namely the one that sorts the input. >>> >>> For the full exposition, see >>> >>> http://apfelmus.nfshost.com/random-permutations.html >> I haven't been following the thread, but my initial reaction >> would have been something like use System.Random.randoms to >> get a list rs and then do (roughly) >> >> randomPerm = map snd . sortBy (compare `on` fst) . zip rs >> >> How bad is that? I mean, how unfair does it get? > > It's fair, but may duplicate elements, i.e. it doesn't necessarily > create a permutation. For example, rs could be something like > > rs = [5,3,3,3,2,4] > How about using random doubles? randomPerm xs = fmap (map snd . sort . flip zip xs) rs where rs = fmap (randoms . mkStdGen) randomIO :: IO [Double] From felipe.lessa at gmail.com Sun Feb 15 07:23:57 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Sun Feb 15 07:13:38 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Re: permuting a list In-Reply-To: References: <1234430432.5888.23.camel@arjuna> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> <200902122046.22430.daniel.is.fischer@web.de> Message-ID: On Sun, Feb 15, 2009 at 9:47 AM, Heinrich Apfelmus wrote: > It's fair, but may duplicate elements, i.e. it doesn't necessarily > create a permutation. For example, rs could be something like > > rs = [5,3,3,3,2,4] > But our sort doesn't discard values when the keys are the same. For example, [1,2,3,4] == map snd . sortBy (compare `on` fst) . zip (repeat 1) $ [1,2,3,4] Nothing gets duplicated. Or did I miss something? -- Felipe. From paul at cogito.org.uk Sun Feb 15 10:05:21 2009 From: paul at cogito.org.uk (Paul Johnson) Date: Sun Feb 15 21:15:58 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Re: permuting a list In-Reply-To: <4998091B.2030403@um.es> References: <1234430432.5888.23.camel@arjuna> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> <200902122046.22430.daniel.is.fischer@web.de> <4998091B.2030403@um.es> Message-ID: <49982F31.1030009@cogito.org.uk> See http://okmij.org/ftp/Haskell/perfect-shuffle.txt Paul. From lemming at henning-thielemann.de Sat Feb 14 19:04:32 2009 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sun Feb 15 21:17:46 2009 Subject: [Haskell-beginners] Re: permuting a list In-Reply-To: <200902141746.52960.daniel.is.fischer@web.de> References: <1234430432.5888.23.camel@arjuna> <200902122046.22430.daniel.is.fischer@web.de> <200902141746.52960.daniel.is.fischer@web.de> Message-ID: On Sat, 14 Feb 2009, Daniel Fischer wrote: > Am Samstag, 14. Februar 2009 16:37 schrieb Heinrich Apfelmus: >> >> For the full exposition, see >> >> http://apfelmus.nfshost.com/random-permutations.html > > Excellent work, thanks. Interesting read. Btw. a further development of the PFP library is also on Hackage: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/probability From apfelmus at quantentunnel.de Mon Feb 16 03:41:50 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Mon Feb 16 03:30:34 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Re: permuting a list In-Reply-To: <4998091B.2030403@um.es> References: <1234430432.5888.23.camel@arjuna> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> <200902122046.22430.daniel.is.fischer@web.de> <4998091B.2030403@um.es> Message-ID: Alberto Ruiz wrote: > > How about using random doubles? > > randomPerm xs = fmap (map snd . sort . flip zip xs) rs > where rs = fmap (randoms . mkStdGen) randomIO :: IO [Double] Interesting idea. The chance of duplicates should be negligible now, but that's because we're using a large amount of random bits, far more than n! would require. Regards, apfelmus -- http://apfelmus.nfshost.com From aruiz at um.es Mon Feb 16 04:24:59 2009 From: aruiz at um.es (Alberto Ruiz) Date: Mon Feb 16 04:14:30 2009 Subject: [Haskell-beginners] Re: [Haskell-cafe] Re: permuting a list In-Reply-To: References: <1234430432.5888.23.camel@arjuna> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> <200902122046.22430.daniel.is.fischer@web.de> <4998091B.2030403@um.es> Message-ID: <499930EB.90206@um.es> Heinrich Apfelmus wrote: > Alberto Ruiz wrote: >> How about using random doubles? >> >> randomPerm xs = fmap (map snd . sort . flip zip xs) rs >> where rs = fmap (randoms . mkStdGen) randomIO :: IO [Double] > > Interesting idea. The chance of duplicates should be negligible now, but > that's because we're using a large amount of random bits, far more than > n! would require. Another possibility is using infinite lists of random bits as keys. Then we only extract from the random number generator the number of bits required to avoid duplicates. -Alberto From jon.fairbairn at cl.cam.ac.uk Mon Feb 16 04:58:43 2009 From: jon.fairbairn at cl.cam.ac.uk (Jon Fairbairn) Date: Mon Feb 16 04:49:29 2009 Subject: [Haskell-beginners] Re: permuting a list References: <1234430432.5888.23.camel@arjuna> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> <200902122046.22430.daniel.is.fischer@web.de> <4998091B.2030403@um.es> <49982F31.1030009@cogito.org.uk> Message-ID: Paul Johnson writes: > See http://okmij.org/ftp/Haskell/perfect-shuffle.txt I should have read that first time round! -- J?n Fairbairn Jon.Fairbairn@cl.cam.ac.uk http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2009-01-31) From alios at alios.org Mon Feb 16 09:28:53 2009 From: alios at alios.org (Markus Barenhoff) Date: Mon Feb 16 09:18:19 2009 Subject: [Haskell-beginners] multi parameter classes and instance declarations Message-ID: <20090216142853.GB66612@beteigeuze.alios.net> Good Afternoon, i'am trying to express something like this here: > -- CI.hs http://pastebin.com/f5b17cf57 > {-# OPTIONS -XMultiParamTypeClasses #-} > module CI(D,f) where > class B b > class (B b) => A a b where > f :: b > data D = D > instance B D > instance A D D where > f = D > -- CI.hs > -- MultiClassTest.hs http://pastebin.com/f1c481e8d > import CI > a = f > -- MultiClassTest.hs ghc output: MultiClassTest.hs:4:4: No instance for (CI.A a D) arising from a use of `f' at MultiClassTest.hs:4:4 Possible fix: add an instance declaration for (CI.A a D) In the expression: f In the definition of `a': a = f Failed, modules loaded: CI. when opening MultiClassTest.hs it looks like the instance declaration gets not important, but I think it might have a reson, that the ghc rejects that code... Regards Markus -- Markus Barenhoff - M??nster Germany,Europe,Earth sip:alios@alios.org - iax2:alios@alios.org - xmpp:alios@jabber.ccc.de gpg:0xAE7C7759 fp:79 64 AA D9 B7 16 F5 06 6A 88 5F A9 4D 49 45 BB -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 479 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090216/314acda6/attachment.bin From alios at alios.org Mon Feb 16 09:40:35 2009 From: alios at alios.org (Markus Barenhoff) Date: Mon Feb 16 09:29:54 2009 Subject: [Haskell-beginners] multi parameter classes and instance declarations In-Reply-To: <20090216142853.GB66612@beteigeuze.alios.net> References: <20090216142853.GB66612@beteigeuze.alios.net> Message-ID: <20090216144035.GC66612@beteigeuze.alios.net> On Mon 16.02 15:28, Markus Barenhoff wrote: > Good Afternoon, > > i'am trying to express something like this here: > > > -- CI.hs http://pastebin.com/f5b17cf57 > > {-# OPTIONS -XMultiParamTypeClasses #-} > > > module CI(D,f) where > > > class B b > > > class (B b) => A a b where > > f :: b > > > data D = D > > > instance B D > > > instance A D D where > > f = D > > -- CI.hs > > > -- MultiClassTest.hs http://pastebin.com/f1c481e8d > > import CI > > > a = f > > -- MultiClassTest.hs I forgot to mention that constrain a :: D does leed to the same ghc messages. > > ghc output: > MultiClassTest.hs:4:4: > No instance for (CI.A a D) > arising from a use of `f' at MultiClassTest.hs:4:4 > Possible fix: add an instance declaration for (CI.A a D) > In the expression: f > In the definition of `a': a = f > Failed, modules loaded: CI. > Markus -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 479 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090216/d2963b12/attachment.bin From daniel.is.fischer at web.de Mon Feb 16 10:17:52 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Mon Feb 16 10:04:38 2009 Subject: [Haskell-beginners] multi parameter classes and instance declarations In-Reply-To: <20090216144035.GC66612@beteigeuze.alios.net> References: <20090216142853.GB66612@beteigeuze.alios.net> <20090216144035.GC66612@beteigeuze.alios.net> Message-ID: <200902161617.52309.daniel.is.fischer@web.de> Am Montag, 16. Februar 2009 15:40 schrieb Markus Barenhoff: > On Mon 16.02 15:28, Markus Barenhoff wrote: > > Good Afternoon, > > > > i'am trying to express something like this here: > > > -- CI.hs http://pastebin.com/f5b17cf57 > > > {-# OPTIONS -XMultiParamTypeClasses #-} > > > > > > module CI(D,f) where > > > > > > class B b > > > > > > class (B b) => A a b where > > > f :: b > > > > > > data D = D > > > > > > instance B D > > > > > > instance A D D where > > > f = D > > > -- CI.hs > > > > > > -- MultiClassTest.hs http://pastebin.com/f1c481e8d > > > import CI > > > > > > a = f > > > -- MultiClassTest.hs > > I forgot to mention that constrain a :: D does leed to the same > ghc messages. > > > ghc output: > > MultiClassTest.hs:4:4: > > No instance for (CI.A a D) > > arising from a use of `f' at MultiClassTest.hs:4:4 > > Possible fix: add an instance declaration for (CI.A a D) > > In the expression: f > > In the definition of `a': a = f > > Failed, modules loaded: CI. > GHC doesn't know that there's no other instance A a D besides the given instance A D D, so it doesn't know which instance to select (suppose there were an instance A Bool D where f = undefined, then it's clear that the instance to use can't be decided). Since class A is not exported, there can't be without changing CI, so one might think it would be reasonable to use the only existing instance of A and be done with it. However, GHC treats type classes with an open world assumption (i.e. doesn't select instances according to which instances it currently knows about, but what instances there potentially might be). To make f usable at all, you must make the type a somehow reachable from f (e.g. by adding a functional dependency: {-# LANGUAGE FunctionalDependencies #-} class (B b) => A a b | b -> a where f :: b -- the | b -> a part means that type b uniquely determines type a ) > Markus Cheers, Daniel From miguel.pignatelli at uv.es Mon Feb 16 10:32:23 2009 From: miguel.pignatelli at uv.es (Miguel Pignatelli) Date: Mon Feb 16 10:22:03 2009 Subject: [Haskell-beginners] Indentation of local functions In-Reply-To: References: <1234430432.5888.23.camel@arjuna> <20090212183329.GA2931@seas.upenn.edu> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> <200902122046.22430.daniel.is.fischer@web.de> <4998091B.2030403@um.es> <49982F31.1030009@cogito.org.uk> Message-ID: <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> Hi all, This is my first post in this forum, I'm pretty new to Haskell (although I have some previous experience in functional programming with OCaml). I'm trying to write the typical function that determines if a list is a palindrome. The typical answer would be something like: isPalindrome xs = xs == (reverse xs) But I find this pretty inefficient (duplication of the list and double of needed comparisons). So I tried my own version using just indexes: isPalindrome xs = isPalindrome' 0 (length xs) where isPalindrome' i j = if i == j -- line 43 then True else if (xs !! i) == (xs !! (j-1)) then isPalindrome' (i+1) (j-1) else False But, when trying to load this in ghci it throws the following error: xxx.hs:43:12: parse error (possibly incorrect indentation) Failed, modules loaded: none. (Line 43 is marked in the code) I seems that the definition of isPalindrome' must be in one line. So, this works as expected: isPalindrome xs = isPalindrome' 0 (length xs) where isPalindrome' i j = if i == j then True else if (xs !! i) == (xs !! (j-1)) then isPalindrome' (i+1) (j-1) else False Is there any way to make the local definition of isPalindrome' more readable? Any help in understanding this would be appreciated Thanks in advance, M; -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090216/928bea69/attachment-0001.htm From wagner.andrew at gmail.com Mon Feb 16 10:58:36 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Mon Feb 16 10:48:01 2009 Subject: [Haskell-beginners] Indentation of local functions In-Reply-To: <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> References: <1234430432.5888.23.camel@arjuna> <20CD3B63-7486-4749-BB64-D6A50A83DEF7@gmail.com> <200902122046.22430.daniel.is.fischer@web.de> <4998091B.2030403@um.es> <49982F31.1030009@cogito.org.uk> <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> Message-ID: Here's one solution:isPalindrome xs = isPalindrome' 0 (length xs) where isPalindrome' i j = if i == j then True else check i j check i j = if (xs !! i) == (xs !! (j-1)) then recurse i j else False recurse i j = isPalindrome' (i+1) (j-1) On Mon, Feb 16, 2009 at 10:32 AM, Miguel Pignatelli wrote: > Hi all, > This is my first post in this forum, I'm pretty new to Haskell (although I > have some previous experience in functional programming with OCaml). > > I'm trying to write the typical function that determines if a list is a > palindrome. > The typical answer would be something like: > > isPalindrome xs = xs == (reverse xs) > > But I find this pretty inefficient (duplication of the list and double of > needed comparisons). > So I tried my own version using just indexes: > > isPalindrome xs = > isPalindrome' 0 (length xs) > where isPalindrome' i j = > if i == j -- line 43 > then True > else > if (xs !! i) == (xs !! (j-1)) > then isPalindrome' (i+1) (j-1) > else False > > But, when trying to load this in ghci it throws the following error: > > xxx.hs:43:12: parse error (possibly incorrect indentation) > Failed, modules loaded: none. > (Line 43 is marked in the code) > > I seems that the definition of isPalindrome' must be in one line. So, > this works as expected: > > isPalindrome xs = > isPalindrome' 0 (length xs) > where isPalindrome' i j = if i == j then True else if (xs !! i) == > (xs !! (j-1)) then isPalindrome' (i+1) (j-1) else False > > Is there any way to make the local definition of isPalindrome' more > readable? > > Any help in understanding this would be appreciated > > Thanks in advance, > > M; > > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090216/f2a8e955/attachment.htm From daniel.is.fischer at web.de Mon Feb 16 11:05:19 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Mon Feb 16 10:52:15 2009 Subject: [Haskell-beginners] Indentation of local functions In-Reply-To: <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> References: <1234430432.5888.23.camel@arjuna> <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> Message-ID: <200902161705.19378.daniel.is.fischer@web.de> Am Montag, 16. Februar 2009 16:32 schrieb Miguel Pignatelli: > Hi all, > > This is my first post in this forum, I'm pretty new to Haskell > (although I have some previous experience in functional programming > with OCaml). > > I'm trying to write the typical function that determines if a list is > a palindrome. > The typical answer would be something like: > > isPalindrome xs = xs == (reverse xs) > > But I find this pretty inefficient (duplication of the list and double > of needed comparisons). > So I tried my own version using just indexes: > > isPalindrome xs = > isPalindrome' 0 (length xs) > where isPalindrome' i j = > if i == j -- line 43 > then True > else > if (xs !! i) == (xs !! (j-1)) > then isPalindrome' (i+1) (j-1) > else False > > But, when trying to load this in ghci it throws the following error: > > xxx.hs:43:12: parse error (possibly incorrect indentation) > Failed, modules loaded: none. > (Line 43 is marked in the code) > > I seems that the definition of isPalindrome' must be in one line. So, > this works as expected: > > isPalindrome xs = > isPalindrome' 0 (length xs) > where isPalindrome' i j = if i == j then True else if (xs !! i) > == (xs !! (j-1)) then isPalindrome' (i+1) (j-1) else False > > Is there any way to make the local definition of isPalindrome' more > readable? > Yes, it would be horrible to look at Haskell code if there weren't. The problem is that originally, the code for isPalindrome' was indented less than the function name. Specifically, the first relevant token (i.e. not whitespace or comments) after the keywords do, let, where, case ... of opens up a new scope, which lasts until something is indented less or equally far. To not suffer from e-mailing programmes behaviour regarding leading spaces on a line, I replace those with '?', then a more readable formatting of your code would be isPalindrome xs = isPalindrome' 0 (length xs) ???where ??????isPalindrome' i j ?????????| j <= i = True ?????????| xs !! i /= xs !! (j-1) = False ?????????| otherwise = isPalindrome (i+1) (j-1) I have replaced your nested ifs by guards (increases readability, IMO) and corrected the stopping condition so that it also works on words of odd length. However, note that Haskell lists aren't arrays, but singly linked lists, so to find xs !! k, all the first (k+1) cells of the list must be visited, making your algorithm less efficient than the naive one, since you must visit O((length xs)^2) cells. > Any help in understanding this would be appreciated > > Thanks in advance, > > M; Cheers, Daniel From alan.cameron at iname.com Mon Feb 16 11:26:14 2009 From: alan.cameron at iname.com (Alan Cameron) Date: Mon Feb 16 11:15:50 2009 Subject: [Haskell-beginners] Palindromic solution?? Message-ID: <777D4A2044B74D3582301B660DFACBAB@ALANXPS> >Date: Mon, 16 Feb 2009 16:32:23 +0100 >From: Miguel Pignatelli >Subject: [Haskell-beginners] Indentation of local functions >To: beginners@haskell.org >Message-ID: <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> >Content-Type: text/plain; charset="us-ascii" > >Hi all, > >This is my first post in this forum, I'm pretty new to Haskell (although I >have some previous experience in functional programming with OCaml) > >I'm trying to write the typical function that determines if a list is a >palindrome. >the typical answer would be something like: > >isPalindrome xs = xs == (reverse xs) > >But I find this pretty inefficient (duplication of the list and double of >needed comparisons). >So I tried my own version using just indexes: > >isPalindrome xs = > isPalindrome' 0 (length xs) > where isPalindrome' i j = > if i == j -- line 43 > then True > else > if (xs !! i) == (xs !! (j-1)) > then isPalindrome' (i+1) (j-1) > else False > >But, when trying to load this in ghci it throws the following error: > >xxx.hs:43:12: parse error (possibly incorrect indentation) Failed, modules >loaded: none. >(Line 43 is marked in the code) > >I seems that the definition of isPalindrome' must be in one line. So, this >works as expected: > >isPalindrome xs = > isPalindrome' 0 (length xs) > where isPalindrome' i j = if i == j then True else if (xs !! i) == (xs !! (j-1)) then isPalindrome' (i+1) (j-1) else False > >Is there any way to make the local definition of isPalindrome' more >readable? > >Any help in understanding this would be appreciated > >Thanks in advance, > I have found one solution to your problem isPalindrome xs = isPalindrome' 0 (length xs) where isPalindrome' i j = if i == j -- line 43 then True else if (xs !! i) == (xs !! (j-1)) then isPalindrome' (i+1) (j-1) else False This loads without error but poses a second problem it generates an index too large exception. Alan Cameron From miguel.pignatelli at uv.es Mon Feb 16 11:32:55 2009 From: miguel.pignatelli at uv.es (Miguel Pignatelli) Date: Mon Feb 16 11:22:24 2009 Subject: [Haskell-beginners] Palindromic solution?? In-Reply-To: <777D4A2044B74D3582301B660DFACBAB@ALANXPS> References: <777D4A2044B74D3582301B660DFACBAB@ALANXPS> Message-ID: Yes, the index too large exception is a bug in my original code, it should check for "i >= j" instead of "i==j" Thanks, M; El 16/02/2009, a las 17:26, Alan Cameron escribi?: >> Date: Mon, 16 Feb 2009 16:32:23 +0100 >> From: Miguel Pignatelli >> Subject: [Haskell-beginners] Indentation of local functions >> To: beginners@haskell.org >> Message-ID: <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> >> Content-Type: text/plain; charset="us-ascii" >> >> Hi all, >> >> This is my first post in this forum, I'm pretty new to Haskell >> (although I >> have some previous experience in functional programming with OCaml) >> >> I'm trying to write the typical function that determines if a list >> is a >> palindrome. >> the typical answer would be something like: >> >> isPalindrome xs = xs == (reverse xs) >> >> But I find this pretty inefficient (duplication of the list and >> double of >> needed comparisons). >> So I tried my own version using just indexes: >> >> isPalindrome xs = >> isPalindrome' 0 (length xs) >> where isPalindrome' i j = >> if i == j -- line 43 >> then True >> else >> if (xs !! i) == (xs !! (j-1)) >> then isPalindrome' (i+1) (j-1) >> else False >> >> But, when trying to load this in ghci it throws the following error: >> >> xxx.hs:43:12: parse error (possibly incorrect indentation) Failed, >> modules >> loaded: none. >> (Line 43 is marked in the code) >> >> I seems that the definition of isPalindrome' must be in one line. >> So, this >> works as expected: >> >> isPalindrome xs = >> isPalindrome' 0 (length xs) >> where isPalindrome' i j = if i == j then True else if (xs !! i) >> == > (xs !! (j-1)) then isPalindrome' (i+1) (j-1) else False >> >> Is there any way to make the local definition of isPalindrome' more >> readable? >> >> Any help in understanding this would be appreciated >> >> Thanks in advance, >> > I have found one solution to your problem > > isPalindrome xs = > isPalindrome' 0 (length xs) > where > isPalindrome' i j = > if i == j -- line 43 > then True > else > if (xs !! i) == (xs !! (j-1)) > then isPalindrome' (i+1) (j-1) > else False > > This loads without error but poses a second problem it generates an > index > too large exception. > > > > > Alan Cameron > > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > From tom.davie at gmail.com Mon Feb 16 13:04:18 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Mon Feb 16 12:53:48 2009 Subject: [Haskell-beginners] Palindromic solution?? In-Reply-To: <777D4A2044B74D3582301B660DFACBAB@ALANXPS> References: <777D4A2044B74D3582301B660DFACBAB@ALANXPS> Message-ID: <6A3AD739-A230-48D1-9641-4C9A86B8D65D@gmail.com> On 16 Feb 2009, at 17:26, Alan Cameron wrote: >> Date: Mon, 16 Feb 2009 16:32:23 +0100 >> From: Miguel Pignatelli >> Subject: [Haskell-beginners] Indentation of local functions >> To: beginners@haskell.org >> Message-ID: <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> >> Content-Type: text/plain; charset="us-ascii" >> >> Hi all, >> >> This is my first post in this forum, I'm pretty new to Haskell >> (although I >> have some previous experience in functional programming with OCaml) >> >> I'm trying to write the typical function that determines if a list >> is a >> palindrome. >> the typical answer would be something like: >> >> isPalindrome xs = xs == (reverse xs) >> >> But I find this pretty inefficient (duplication of the list and >> double of >> needed comparisons). >> So I tried my own version using just indexes: >> >> isPalindrome xs = >> isPalindrome' 0 (length xs) >> where isPalindrome' i j = >> if i == j -- line 43 >> then True >> else >> if (xs !! i) == (xs !! (j-1)) >> then isPalindrome' (i+1) (j-1) >> else False >> >> But, when trying to load this in ghci it throws the following error: >> >> xxx.hs:43:12: parse error (possibly incorrect indentation) Failed, >> modules >> loaded: none. >> (Line 43 is marked in the code) >> >> I seems that the definition of isPalindrome' must be in one line. >> So, this >> works as expected: >> >> isPalindrome xs = >> isPalindrome' 0 (length xs) >> where isPalindrome' i j = if i == j then True else if (xs !! i) >> == > (xs !! (j-1)) then isPalindrome' (i+1) (j-1) else False >> >> Is there any way to make the local definition of isPalindrome' more >> readable? >> >> Any help in understanding this would be appreciated >> >> Thanks in advance, Of note by the way ? the new solution is less efficient than the old one, for each letter that it compares it must traverse the list to find the (j-1)'th element. We can get a nice efficient solution by simply using the take function: isPalindrome xs = take l xs == (take l $ reverse xs) where l = length xs `div` 2 Bob From bayer at cpw.math.columbia.edu Mon Feb 16 13:30:46 2009 From: bayer at cpw.math.columbia.edu (Dave Bayer) Date: Mon Feb 16 13:20:13 2009 Subject: [Haskell-beginners] Palindromic solution?? In-Reply-To: <6A3AD739-A230-48D1-9641-4C9A86B8D65D@gmail.com> References: <777D4A2044B74D3582301B660DFACBAB@ALANXPS> <6A3AD739-A230-48D1-9641-4C9A86B8D65D@gmail.com> Message-ID: <45A0058E-F1C3-4D11-BBAC-7A2E3D8DC56E@math.columbia.edu> Here's a solution harder on the machine, easier on the brain: isPalindrome :: Eq a => [a] -> Bool isPalindrome xs = and $ zipWith (==) xs $ reverse xs On Feb 16, 2009, at 1:04 PM, Thomas Davie wrote: > isPalindrome xs = take l xs == (take l $ reverse xs) > where l = length xs `div` 2 From tom.davie at gmail.com Mon Feb 16 13:38:50 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Mon Feb 16 13:28:20 2009 Subject: [Haskell-beginners] Palindromic solution?? In-Reply-To: <45A0058E-F1C3-4D11-BBAC-7A2E3D8DC56E@math.columbia.edu> References: <777D4A2044B74D3582301B660DFACBAB@ALANXPS> <6A3AD739-A230-48D1-9641-4C9A86B8D65D@gmail.com> <45A0058E-F1C3-4D11-BBAC-7A2E3D8DC56E@math.columbia.edu> Message-ID: On 16 Feb 2009, at 19:30, Dave Bayer wrote: > Here's a solution harder on the machine, easier on the brain: > > isPalindrome :: Eq a => [a] -> Bool > isPalindrome xs = and $ zipWith (==) xs $ reverse xs Lets just tidy that up a little... isPalindrome = (and . zipWith (==)) <*> reverse But I don't see how either is easier on the brain than xs == reverse xs. Bob From miguel.pignatelli at uv.es Mon Feb 16 18:24:23 2009 From: miguel.pignatelli at uv.es (Miguel Pignatelli) Date: Mon Feb 16 18:13:56 2009 Subject: [Haskell-beginners] Indentation of local functions In-Reply-To: <200902161705.19378.daniel.is.fischer@web.de> References: <1234430432.5888.23.camel@arjuna> <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> <200902161705.19378.daniel.is.fischer@web.de> Message-ID: <991970A6-4BFD-43CB-AB03-6060F2E59746@uv.es> Nice! Thanks a lot for the explanation. (and to the others that have replied!) M; El 16/02/2009, a las 17:05, Daniel Fischer escribi?: > Am Montag, 16. Februar 2009 16:32 schrieb Miguel Pignatelli: >> Hi all, >> >> This is my first post in this forum, I'm pretty new to Haskell >> (although I have some previous experience in functional programming >> with OCaml). >> >> I'm trying to write the typical function that determines if a list is >> a palindrome. >> The typical answer would be something like: >> >> isPalindrome xs = xs == (reverse xs) >> >> But I find this pretty inefficient (duplication of the list and >> double >> of needed comparisons). >> So I tried my own version using just indexes: >> >> isPalindrome xs = >> isPalindrome' 0 (length xs) >> where isPalindrome' i j = >> if i == j -- line 43 >> then True >> else >> if (xs !! i) == (xs !! (j-1)) >> then isPalindrome' (i+1) (j-1) >> else False >> >> But, when trying to load this in ghci it throws the following error: >> >> xxx.hs:43:12: parse error (possibly incorrect indentation) >> Failed, modules loaded: none. >> (Line 43 is marked in the code) >> >> I seems that the definition of isPalindrome' must be in one line. So, >> this works as expected: >> >> isPalindrome xs = >> isPalindrome' 0 (length xs) >> where isPalindrome' i j = if i == j then True else if (xs !! i) >> == (xs !! (j-1)) then isPalindrome' (i+1) (j-1) else False >> >> Is there any way to make the local definition of isPalindrome' more >> readable? >> > > Yes, it would be horrible to look at Haskell code if there weren't. > The problem is that originally, the code for isPalindrome' was > indented less > than the function name. Specifically, the first relevant token (i.e. > not > whitespace or comments) after the keywords do, let, where, case ... of > opens up a new scope, which lasts until something is indented less > or equally > far. > To not suffer from e-mailing programmes behaviour regarding leading > spaces on > a line, I replace those with '?', then a more readable formatting of > your > code would be > > isPalindrome xs = isPalindrome' 0 (length xs) > ???where > ??????isPalindrome' i j > ?????????| j <= i = True > ?????????| xs !! i /= xs !! (j-1) = False > ?????????| otherwise = isPalindrome (i+1) (j-1) > > I have replaced your nested ifs by guards (increases readability, > IMO) and > corrected the stopping condition so that it also works on words of odd > length. > > However, note that Haskell lists aren't arrays, but singly linked > lists, so to > find xs !! k, all the first (k+1) cells of the list must be visited, > making > your algorithm less efficient than the naive one, since you must visit > O((length xs)^2) cells. > >> Any help in understanding this would be appreciated >> >> Thanks in advance, >> >> M; > > Cheers, > Daniel > > From rivercheng at gmail.com Tue Feb 17 03:59:42 2009 From: rivercheng at gmail.com (ChengWei) Date: Tue Feb 17 03:49:06 2009 Subject: [Haskell-beginners] Indentation of local functions In-Reply-To: <991970A6-4BFD-43CB-AB03-6060F2E59746@uv.es> References: <1234430432.5888.23.camel@arjuna> <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> <200902161705.19378.daniel.is.fischer@web.de> <991970A6-4BFD-43CB-AB03-6060F2E59746@uv.es> Message-ID: Dear all: Do we really have better method than this version (if list is used as the data structure): isPalindrome xs = xs == (reverse xs)? Since we need to get the last xs, we already has to visit all the elements, so nothing can be saved. To avoid the double comparisons, maybe we will use: let l = length xs / 2 in take l x == take l $ reverse xs But the length function added one more extra iteration. We could write our own reverse function to obtain the length in the same time with reversing. But the gain is not large enough to justify the optimization in my opinion. Best Regards, Cheng Wei On Tue, Feb 17, 2009 at 7:24 AM, Miguel Pignatelli wrote: > Nice! > Thanks a lot for the explanation. (and to the others that have replied!) > > M; > > > El 16/02/2009, a las 17:05, Daniel Fischer escribi?: > > > Am Montag, 16. Februar 2009 16:32 schrieb Miguel Pignatelli: >> >>> Hi all, >>> >>> This is my first post in this forum, I'm pretty new to Haskell >>> (although I have some previous experience in functional programming >>> with OCaml). >>> >>> I'm trying to write the typical function that determines if a list is >>> a palindrome. >>> The typical answer would be something like: >>> >>> isPalindrome xs = xs == (reverse xs) >>> >>> But I find this pretty inefficient (duplication of the list and double >>> of needed comparisons). >>> So I tried my own version using just indexes: >>> >>> isPalindrome xs = >>> isPalindrome' 0 (length xs) >>> where isPalindrome' i j = >>> if i == j -- line 43 >>> then True >>> else >>> if (xs !! i) == (xs !! (j-1)) >>> then isPalindrome' (i+1) (j-1) >>> else False >>> >>> But, when trying to load this in ghci it throws the following error: >>> >>> xxx.hs:43:12: parse error (possibly incorrect indentation) >>> Failed, modules loaded: none. >>> (Line 43 is marked in the code) >>> >>> I seems that the definition of isPalindrome' must be in one line. So, >>> this works as expected: >>> >>> isPalindrome xs = >>> isPalindrome' 0 (length xs) >>> where isPalindrome' i j = if i == j then True else if (xs !! i) >>> == (xs !! (j-1)) then isPalindrome' (i+1) (j-1) else False >>> >>> Is there any way to make the local definition of isPalindrome' more >>> readable? >>> >>> >> Yes, it would be horrible to look at Haskell code if there weren't. >> The problem is that originally, the code for isPalindrome' was indented >> less >> than the function name. Specifically, the first relevant token (i.e. not >> whitespace or comments) after the keywords do, let, where, case ... of >> opens up a new scope, which lasts until something is indented less or >> equally >> far. >> To not suffer from e-mailing programmes behaviour regarding leading spaces >> on >> a line, I replace those with '?', then a more readable formatting of your >> code would be >> >> isPalindrome xs = isPalindrome' 0 (length xs) >> ???where >> ??????isPalindrome' i j >> ?????????| j <= i = True >> ?????????| xs !! i /= xs !! (j-1) = False >> ?????????| otherwise = isPalindrome (i+1) (j-1) >> >> I have replaced your nested ifs by guards (increases readability, IMO) and >> corrected the stopping condition so that it also works on words of odd >> length. >> >> However, note that Haskell lists aren't arrays, but singly linked lists, >> so to >> find xs !! k, all the first (k+1) cells of the list must be visited, >> making >> your algorithm less efficient than the naive one, since you must visit >> O((length xs)^2) cells. >> >> Any help in understanding this would be appreciated >>> >>> Thanks in advance, >>> >>> M; >>> >> >> Cheers, >> Daniel >> >> >> > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090217/751562a6/attachment.htm From Christian.Maeder at dfki.de Tue Feb 17 04:09:41 2009 From: Christian.Maeder at dfki.de (Christian Maeder) Date: Tue Feb 17 03:59:03 2009 Subject: [Haskell-beginners] Re: Indentation of local functions In-Reply-To: <200902161705.19378.daniel.is.fischer@web.de> References: <1234430432.5888.23.camel@arjuna> <90C28A9E-A67D-47CA-8416-5F1C5C27A1F9@uv.es> <200902161705.19378.daniel.is.fischer@web.de> Message-ID: <499A7ED5.4070200@dfki.de> Daniel Fischer wrote: > isPalindrome xs = isPalindrome' 0 (length xs) > ???where > ??????isPalindrome' i j > ?????????| j <= i = True > ?????????| xs !! i /= xs !! (j-1) = False > ?????????| otherwise = isPalindrome (i+1) (j-1) I only want to point out, that it is possible to put "where" ("do" or "let") at the end of the previous line, but a separate line for "where" is a good idea, too. > I have replaced your nested ifs by guards (increases readability, IMO) and > corrected the stopping condition so that it also works on words of odd > length. Instead of course I prefer boolean expressions in some cases: isPalindrome xs = isPalindrome' 0 (length xs) where isPalindrome' i j = j <= i || xs !! i == xs !! (j-1) && isPalindrome' (i+1) (j-1) > However, note that Haskell lists aren't arrays, but singly linked lists, so to > find xs !! k, all the first (k+1) cells of the list must be visited, making > your algorithm less efficient than the naive one, since you must visit > O((length xs)^2) cells. Right, and only computing the length takes n steps, which is hard to avoid when one wants to avoid double equality tests. isPalindrome xs = and $ zipWith (==) xs $ reverse $ drop (div (length xs + 1) 2) xs Cheers Christian From sergey at mikhanov.com Thu Feb 19 09:56:02 2009 From: sergey at mikhanov.com (Sergey V. Mikhanov) Date: Thu Feb 19 09:45:22 2009 Subject: [Haskell-beginners] Sequential IO processing Message-ID: Hi community, I am making my first steps in Haskell, reading Haskell wikibook and now stuck with one of the excercises, namely this one: Implement a function sequenceIO :: [IO a] -> IO [a]. Given a list of actions, this function runs each of the actions in order and returns all their results as a list. This is what I came with: ioOne :: Num a => IO a ioOne = do print guid return guid where guid = 2 ioTwo :: Num a => IO a ioTwo = do print guid return guid where guid = 3 sequenceIO :: Num a => [IO a] -> IO [a] sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x return result : sequenceIO xs First two functions are there because of the invocation that I've planned: sequenceIO [getGuid, getNextGuid]. However, this could not be compiled (GHC): Couldn't match expected type `[m a]' against inferred type `IO [a]' In the second argument of `(:)', namely `sequenceIO xs' In the expression: return result : sequenceIO xs In the expression: do result <- x return result : sequenceIO xs Fine, I thought, something wrong with the type of the 'sequenceIO xs' (becasue I am sure the type of 'result' is fine). So I wrote another program to check what happens to the result of IO action evaluation (namely, which type is assigned): bar :: Num a => IO a bar = do print guid return guid where guid = 2 foo = do result <- bar result This could not be compiled either: No instance for (Num (IO b)) arising from a use of `bar' at auxil.hs:8:19-21 Possible fix: add an instance declaration for (Num (IO b)) In a stmt of a 'do' expression: result <- bar In the expression: do result <- bar result In the definition of `foo': foo = do result <- bar result I am a newbie, so I am interpreting this like "Haskell could not construct Num from the result of invocation of bar, which is of type IO a". But why do I need this at all? When doing console I/O with 'result <- getLine', I do not need to reconstruct String from the result. What am I doing wrong? Where is the failure in reasoning? Thanks, Sergey From wagner.andrew at gmail.com Thu Feb 19 10:19:35 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Thu Feb 19 10:08:51 2009 Subject: [Haskell-beginners] Sequential IO processing In-Reply-To: References: Message-ID: You did really well here. There's just one small detail that you missed, which is causing the problem: > > sequenceIO [] = return [] > sequenceIO (x : xs) = do result <- x > return result : sequenceIO xs > The problem is indeed here. The type of 'sequenceIO xs' is IO [a], but the type of result is 'a'. You can't cons an 'a' onto an 'IO [a]'. Thus, what you need is something like this: sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x xs' <- sequenceIO xs -- to take the list out of the IO Monad return result : xs' On Thu, Feb 19, 2009 at 9:56 AM, Sergey V. Mikhanov wrote: > Hi community, > > I am making my first steps in Haskell, reading Haskell wikibook and > now stuck with one of the excercises, namely this one: > > Implement a function sequenceIO :: [IO a] -> IO [a]. Given a list of > actions, this function runs each of the actions in order and returns > all their results as a list. > > This is what I came with: > > ioOne :: Num a => IO a > > ioOne = do print guid > return guid > where > guid = 2 > > ioTwo :: Num a => IO a > > ioTwo = do print guid > return guid > where > guid = 3 > > sequenceIO :: Num a => [IO a] -> IO [a] > > sequenceIO [] = return [] > sequenceIO (x : xs) = do result <- x > return result : sequenceIO xs > > First two functions are there because of the invocation that I've > planned: sequenceIO [getGuid, getNextGuid]. > > However, this could not be compiled (GHC): > > Couldn't match expected type `[m a]' against inferred type `IO [a]' > In the second argument of `(:)', namely `sequenceIO xs' > In the expression: return result : sequenceIO xs > In the expression: > do result <- x > return result : sequenceIO xs > > Fine, I thought, something wrong with the type of the 'sequenceIO xs' > (becasue I am sure the type of 'result' is fine). So I wrote another > program to check what happens to the result of IO action evaluation > (namely, which type is assigned): > > bar :: Num a => IO a > > bar = do print guid > return guid > where > guid = 2 > > foo = do result <- bar > result > > This could not be compiled either: > > No instance for (Num (IO b)) > arising from a use of `bar' at auxil.hs:8:19-21 > Possible fix: add an instance declaration for (Num (IO b)) > In a stmt of a 'do' expression: result <- bar > In the expression: > do result <- bar > result > In the definition of `foo': > foo = do result <- bar > result > > I am a newbie, so I am interpreting this like "Haskell could not > construct Num from the result of invocation of bar, which is of type > IO a". But why do I need this at all? When doing console I/O with > 'result <- getLine', I do not need to reconstruct String from the > result. > > What am I doing wrong? Where is the failure in reasoning? > > Thanks, > Sergey > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090219/3e166623/attachment.htm From sergey at mikhanov.com Thu Feb 19 10:27:02 2009 From: sergey at mikhanov.com (Sergey V. Mikhanov) Date: Thu Feb 19 10:16:20 2009 Subject: [Haskell-beginners] Sequential IO processing In-Reply-To: References: Message-ID: I tried this earlier as well: sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x resultTail <- sequenceIO xs return result : resultTail This results in: Couldn't match expected type `IO [a]' against inferred type `[m a]' In the expression: return result : resultTail In the expression: do result <- x resultTail <- sequenceIO xs return result : resultTail In the definition of `sequenceIO': sequenceIO (x : xs) = do result <- x resultTail <- sequenceIO xs return result : resultTail >> sequenceIO [] = return [] >> sequenceIO (x : xs) = do result <- x >> return result : sequenceIO xs > > The problem is indeed here. The type of 'sequenceIO xs' is IO [a], but the > type of result is 'a'. You can't cons an 'a' onto an 'IO [a]'. Thus, what > you need is something like this: > sequenceIO [] = return [] > sequenceIO (x : xs) = do result <- x > xs' <- sequenceIO xs -- to take the > list out of the IO Monad > return result : xs' From apfelmus at quantentunnel.de Thu Feb 19 10:32:29 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Thu Feb 19 10:21:02 2009 Subject: [Haskell-beginners] Re: Sequential IO processing In-Reply-To: References: Message-ID: Sergey V. Mikhanov wrote: > I tried this earlier as well: > > sequenceIO [] = return [] > sequenceIO (x : xs) = do result <- x > resultTail <- sequenceIO xs > return result : resultTail The last line should be return (result : resultTail) otherwise it will be parsed as (return result) : resultTail which is not what you want. Regards, apfelmus -- http://apfelmus.nfshost.com From sergey at mikhanov.com Thu Feb 19 10:35:08 2009 From: sergey at mikhanov.com (Sergey V. Mikhanov) Date: Thu Feb 19 10:24:25 2009 Subject: [Haskell-beginners] Re: Sequential IO processing In-Reply-To: References: Message-ID: Now works! Thank you very much -- a nice lesson learned for me. S. >> I tried this earlier as well: >> >> sequenceIO [] = return [] >> sequenceIO (x : xs) = do result <- x >> resultTail <- sequenceIO xs >> return result : resultTail > > The last line should be > > return (result : resultTail) > > otherwise it will be parsed as > > (return result) : resultTail > > which is not what you want. > > > Regards, > apfelmus From felipe.lessa at gmail.com Thu Feb 19 11:06:00 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Thu Feb 19 10:55:17 2009 Subject: [Haskell-beginners] Re: Sequential IO processing In-Reply-To: References: Message-ID: Just a small comment, it's great to see the beginners list being so useful! Thanks, everyone, beginners and 'otherwise'. -- Felipe. From builes.adolfo at googlemail.com Thu Feb 19 18:15:33 2009 From: builes.adolfo at googlemail.com (Adolfo Builes) Date: Thu Feb 19 23:42:50 2009 Subject: [Haskell-beginners] Counting Fruits Message-ID: Hello everyone , I wanted to do a small program which read a txt with fruit's name in each line and then print how many fruits I have of each type. something like these: apple apple and then [(apple,2)] I came up whit this import qualified Data.Map as Map import Data.List import System.IO main = do file <- readFile "fruits.txt" let answer = proccessFile $ lines file putStrLn (show answer) proccessFile :: [String] -> [(String,Int)] proccessFile file = Map.toAscList $ parseFile Map.empty file where parseFile fruits [] = fruits parseFile fruits_map (x:xs) = parseFile (Map.insertWith (+) x 1 fruits_map) xs It works, but I would like to know how would you do it ?, Share different points of view, different code. Was it a good idea to use a Map ?, Did I separate the code in a proper way, I mean pure - impure ? How can we improve the performance ? Best Regards for everyone. Adolfo -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090219/1162574a/attachment.htm From alexander.dunlap at gmail.com Fri Feb 20 00:01:24 2009 From: alexander.dunlap at gmail.com (Alexander Dunlap) Date: Thu Feb 19 23:50:40 2009 Subject: [Haskell-beginners] Counting Fruits In-Reply-To: References: Message-ID: <57526e770902192101n6666ea99h317ea5cb22db7f3c@mail.gmail.com> On Thu, Feb 19, 2009 at 3:15 PM, Adolfo Builes wrote: > Hello everyone , > I wanted to do a small program which read a txt with fruit's name in each > line and then print how many fruits I have of each type. something like > these: > apple > apple > > and then > > [(apple,2)] > > I came up whit this > > import qualified Data.Map as Map > import Data.List > import System.IO > > main = > do > file <- readFile "fruits.txt" > let answer = proccessFile $ lines file > > > putStrLn (show answer) > > proccessFile :: [String] -> [(String,Int)] > proccessFile file = Map.toAscList $ parseFile Map.empty file > where parseFile fruits [] = fruits > parseFile fruits_map (x:xs) = parseFile (Map.insertWith (+) x 1 > fruits_map) xs > > > It works, but I would like to know how would you do it ?, Share different > points of view, different code. Was it a good idea to use a Map ?, Did I > separate the code in a proper way, I mean pure - impure ? How can we > improve the performance ? > > Best Regards for everyone. > > > Adolfo You spelled "process" incorrectly ;). Not a big deal of course, just makes your code a bit cleaner-looking. In terms of actual code, I think "proccessFruits" could probably be rewritten more clearly (and perhaps more efficiently, due to rewrite rules) using a fold. You might also check out the "group" function from Data.List, although that approach would probably be a bit slower. Hope that helps. Alex From apfelmus at quantentunnel.de Fri Feb 20 05:15:03 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Fri Feb 20 05:03:38 2009 Subject: [Haskell-beginners] Re: Counting Fruits In-Reply-To: References: Message-ID: Adolfo Builes wrote: > > I wanted to do a small program which read a txt with fruit's name in each > line and then print how many fruits I have of each type. something like > these: > apple > apple > > and then > > [(apple,2)] > > I came up with this > > import qualified Data.Map as Map > import Data.List > import System.IO > > main = > do > file <- readFile "fruits.txt" > let answer = proccessFile $ lines file > > putStrLn (show answer) > > proccessFile :: [String] -> [(String,Int)] > proccessFile file = Map.toAscList $ parseFile Map.empty file > where parseFile fruits [] = fruits > parseFile fruits_map (x:xs) = parseFile (Map.insertWith (+) > x 1 fruits_map) xs > > > It works, but I would like to know how would you do it ?, Share different > points of view, different code. Was it a good idea to use a Map ?, Did I > separate the code in a proper way, I mean pure - impure ? How can we > improve the performance ? Looks good to me. :) Here's how I would write it main = print . process . lines =<< readFile "fruits.txt" process :: [String] -> [(String,Int)] process = Map.toAscList . foldl f Map.empty where f map x = Map.insertWith (+) x 1 map So, the parseFile function is best expressed as a left fold and function composition is good style. The above works fine for smaller files. If you have larger amounts of data, you will need a few strictness annotations or there will be a space leak. In this case, this means using the functions foldl' and Map.insertWith' instead of foldl and Map.insertWith But I wouldn't bother about that for now. Regards, apfelmus -- http://apfelmus.nfshost.com From mattrussell324 at googlemail.com Fri Feb 20 05:27:50 2009 From: mattrussell324 at googlemail.com (Matt R) Date: Fri Feb 20 05:17:05 2009 Subject: [Haskell-beginners] flip lookup in ghci Message-ID: <2f9e00bc0902200227v3a0213f6v1329969ee174cb05@mail.gmail.com> So what's this all about then? How come a has become ()? ghci> :t lookup lookup :: (Eq a) => a -> [(a, b)] -> Maybe b ghci> :t flip lookup flip lookup :: (Eq a) => [(a, b)] -> a -> Maybe b ghci> let lookupIn = (flip lookup :: (Eq a) => [(a, b)] -> a -> Maybe b ) ghci> :t lookupIn lookupIn :: [((), b)] -> () -> Maybe b From RafaelGCPP.Linux at gmail.com Fri Feb 20 07:11:12 2009 From: RafaelGCPP.Linux at gmail.com (Rafael Gustavo da Cunha Pereira Pinto) Date: Fri Feb 20 07:00:27 2009 Subject: [Haskell-beginners] flip lookup in ghci In-Reply-To: <2f9e00bc0902200227v3a0213f6v1329969ee174cb05@mail.gmail.com> References: <2f9e00bc0902200227v3a0213f6v1329969ee174cb05@mail.gmail.com> Message-ID: <351ff25e0902200411l6b02e8cu40cf1ce50bba9516@mail.gmail.com> you are applying the type to lookup only! try let lookupIn = ((flip lookup ) :: (Eq a) => [(a, b)] -> a -> Maybe b ) On Fri, Feb 20, 2009 at 07:27, Matt R wrote: > So what's this all about then? How come a has become ()? > > ghci> :t lookup > lookup :: (Eq a) => a -> [(a, b)] -> Maybe b > ghci> :t flip lookup > flip lookup :: (Eq a) => [(a, b)] -> a -> Maybe b > ghci> let lookupIn = (flip lookup :: (Eq a) => [(a, b)] -> a -> Maybe b ) > ghci> :t lookupIn > lookupIn :: [((), b)] -> () -> Maybe b > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -- Rafael Gustavo da Cunha Pereira Pinto Electronic Engineer, MSc. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090220/06daa777/attachment.htm From mattrussell324 at googlemail.com Fri Feb 20 07:44:30 2009 From: mattrussell324 at googlemail.com (Matt R) Date: Fri Feb 20 07:33:44 2009 Subject: [Haskell-beginners] flip lookup in ghci In-Reply-To: <351ff25e0902200411l6b02e8cu40cf1ce50bba9516@mail.gmail.com> References: <2f9e00bc0902200227v3a0213f6v1329969ee174cb05@mail.gmail.com> <351ff25e0902200411l6b02e8cu40cf1ce50bba9516@mail.gmail.com> Message-ID: <2f9e00bc0902200444r3b74e314v47851cfea0d7f5fe@mail.gmail.com> Rafael Gustavo da Cunha Pereira Pinto : > you are applying the type to lookup only! > > try let lookupIn = ((flip lookup ) :: (Eq a) => [(a, b)] -> a -> Maybe b ) Oops, I didn't mean to include my attempts at type annotation in my previous email...I meant to write ghci> let lookupIn = flip lookup But it doesn't seem to make any difference either way. I still get ghci> :t lookupIn lookupIn :: [((), b)] -> () -> Maybe b regardless :( -- Matt From felipe.lessa at gmail.com Fri Feb 20 08:06:07 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Fri Feb 20 07:55:21 2009 Subject: [Haskell-beginners] flip lookup in ghci In-Reply-To: <2f9e00bc0902200444r3b74e314v47851cfea0d7f5fe@mail.gmail.com> References: <2f9e00bc0902200227v3a0213f6v1329969ee174cb05@mail.gmail.com> <351ff25e0902200411l6b02e8cu40cf1ce50bba9516@mail.gmail.com> <2f9e00bc0902200444r3b74e314v47851cfea0d7f5fe@mail.gmail.com> Message-ID: Let's try to see what is going on using GHCi 6.10.1: Prelude> :t lookup lookup :: (Eq a) => a -> [(a, b)] -> Maybe b Prelude> :t flip lookup flip lookup :: (Eq a) => [(a, b)] -> a -> Maybe b Everything ok. Lets try binding: Prelude> let f = flip lookup Prelude> :t f f :: [((), b)] -> () -> Maybe b Woops. Whenever you see a type of a function becoming less polymorphic than you expected, try adding a parameter: Prelude> let g x = flip lookup x Prelude> :t g g :: (Eq a) => [(a, b)] -> a -> Maybe b Nice! Let's try again without the monomorphism restriction[1] Prelude> :s -XNoMonomorphismRestriction Prelude> let h = flip lookup Prelude> :t h h :: (Eq a) => [(a, b)] -> a -> Maybe b Prelude> :s -XMonomorphismRestriction So, that's where the culprit lies! As we declared 'f' without a type signature and without explicit arguments, the monomorphism restriction didn't let us overload our function with the 'Eq' class. Note that if we activated all warnings, GHC would tell us that something is wrong: Prelude> :s -Wall Prelude> let j = flip lookup :1:13: Warning: Defaulting the following constraint(s) to type `()' `Eq a' arising from a use of `lookup' at :1:13-18 In the first argument of `flip', namely `lookup' In the expression: flip lookup In the definition of `j': j = flip lookup We can't just remove the 'Eq' constraint, if we want to refine the type of 'lookup' then we need to supply something that implements 'Eq'. As GHC doesn't know what you want to do, it just defaults to (). If, for example, you used the new function in the same let-binding, GHC would infer another type and show no warnings: Prelude> let k = flip lookup; l = k [] (1 :: Int) Prelude> :t k k :: [(Int, b)] -> Int -> Maybe b But note that even if you use the function where you defined it, it can't be polymorphic Prelude> let m = flip lookup; n = m [] (1 :: Int); o = m [] (1 :: Double) :1:52: Couldn't match expected type `Int' against inferred type `Double' In the second argument of `m', namely `(1 :: Double)' In the expression: m [] (1 :: Double) In the definition of `o': o = m [] (1 :: Double) In short: add an explicit parameter or use a type signature. =) Hope that helps! [1] http://www.haskell.org/haskellwiki/Monomorphism_restriction -- Felipe. From magnus at therning.org Fri Feb 20 08:06:22 2009 From: magnus at therning.org (Magnus Therning) Date: Fri Feb 20 07:55:36 2009 Subject: [Haskell-beginners] flip lookup in ghci In-Reply-To: <2f9e00bc0902200444r3b74e314v47851cfea0d7f5fe@mail.gmail.com> References: <2f9e00bc0902200227v3a0213f6v1329969ee174cb05@mail.gmail.com> <351ff25e0902200411l6b02e8cu40cf1ce50bba9516@mail.gmail.com> <2f9e00bc0902200444r3b74e314v47851cfea0d7f5fe@mail.gmail.com> Message-ID: On Fri, Feb 20, 2009 at 12:44 PM, Matt R wrote: > Rafael Gustavo da Cunha Pereira Pinto : >> you are applying the type to lookup only! >> >> try let lookupIn = ((flip lookup ) :: (Eq a) => [(a, b)] -> a -> Maybe b ) > > Oops, I didn't mean to include my attempts at type annotation in my > previous email...I meant to write > > ghci> let lookupIn = flip lookup > > But it doesn't seem to make any difference either way. I still get > > ghci> :t lookupIn > lookupIn :: [((), b)] -> () -> Maybe b > > regardless :( Indeed, how funky: GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Loading package base ... linking ... done. Prelude> :t flip lookup flip lookup :: (Eq a) => [(a, b)] -> a -> Maybe b Prelude> let lookupIn = flip lookup Prelude> :t lookupIn lookupIn :: [((), b)] -> () -> Maybe b Prelude> /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus?therning?org Jabber: magnus?therning?org http://therning.org/magnus identi.ca|twitter: magthe From patrick.leboutillier at gmail.com Fri Feb 20 19:30:05 2009 From: patrick.leboutillier at gmail.com (Patrick LeBoutillier) Date: Fri Feb 20 19:19:20 2009 Subject: [Haskell-beginners] Help with monads (I think...) Message-ID: Hi all, I'm trying to implement the following simple Perl program in Haskell: my $nb_tests = 0 ; sub ok { my $bool = shift ; $nb_tests++ ; print STDOUT ($bool ? "ok" : "nok") . " $nb_tests\n" ; } ok(0) ; ok(1) ; The output is: nok 1 ok 2 I'm pretty much a Haskell newbie, but I know a bit about monads (and have been reading "Real World Haskell"), and I think I need to put the ok function must live inside some kind of state monad. My problem is that I also would like the ok function to perform some IO (as shown above, print). How is a case like this handled? Can my function live in 2 monads? Thanks a lot, Patrick -- ===================== Patrick LeBoutillier Rosem?re, Qu?bec, Canada From daniel.is.fischer at web.de Fri Feb 20 19:54:56 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Fri Feb 20 19:41:30 2009 Subject: [Haskell-beginners] Help with monads (I think...) In-Reply-To: References: Message-ID: <200902210154.56471.daniel.is.fischer@web.de> Am Samstag, 21. Februar 2009 01:30 schrieb Patrick LeBoutillier: > Hi all, > > I'm trying to implement the following simple Perl program in Haskell: > > my $nb_tests = 0 ; > > sub ok { > my $bool = shift ; > $nb_tests++ ; > print STDOUT ($bool ? "ok" : "nok") . " $nb_tests\n" ; > } > > ok(0) ; > ok(1) ; > > The output is: > > nok 1 > ok 2 > > I'm pretty much a Haskell newbie, but I know a bit about monads (and > have been reading "Real World Haskell"), and I think I need to put the > ok function must live inside some kind of state monad. My problem is > that I also would like the ok function to perform some IO (as shown > above, print). > > How is a case like this handled? Can my function live in 2 monads? Yes, it can: -------------------- module OK where import Control.Monad.State ok :: Bool -> StateT Int IO () ok b = do increment nr <- get lift $ putStrLn $ (if b then "ok " else "nok ") ++ show nr increment :: StateT Int IO () increment = modify succ main :: IO () main = evalStateT (ok False >> ok True) 0 -------------------- Loading package base ... linking ... done. [1 of 1] Compiling OK ( OK.hs, interpreted ) Ok, modules loaded: OK. *OK> main Loading package mtl-1.1.0.1 ... linking ... done. nok 1 ok 2 What you need for this kind of stuff is a monad-transformer, there are transformers for most(? many, anyway) monads, recognizable by ending in T. They wrap one monad (here IO) inside another (State), combining their respective abilities. I'm sure there's lots of useful stuff on monad-transformers in the wikibook, too - they should also be treated in RWH, because in real-world apps you tend to need them:) > > > Thanks a lot, > > Patrick Cheers, Daniel From tom.davie at gmail.com Sat Feb 21 04:59:09 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Sat Feb 21 04:48:25 2009 Subject: [Haskell-beginners] Help with monads (I think...) In-Reply-To: References: Message-ID: <3F163140-ACAB-4202-9B98-2269CF2E8A08@gmail.com> On 21 Feb 2009, at 01:30, Patrick LeBoutillier wrote: > Hi all, > > I'm trying to implement the following simple Perl program in Haskell: > > my $nb_tests = 0 ; > > sub ok { > my $bool = shift ; > $nb_tests++ ; > print STDOUT ($bool ? "ok" : "nok") . " $nb_tests\n" ; > } > > ok(0) ; > ok(1) ; > > The output is: > > nok 1 > ok 2 > > I'm pretty much a Haskell newbie, but I know a bit about monads (and > have been reading "Real World Haskell"), and I think I need to put the > ok function must live inside some kind of state monad. My problem is > that I also would like the ok function to perform some IO (as shown > above, print). > > How is a case like this handled? Can my function live in 2 monads? I personally wouldn't use two monads at all for this ? in fact, I'd only use IO in one function: main = putStr . unlines . results inputs . snd . tests $ inputs inputs = [1,2] tests = foldr (\_ (x,l) -> (not x, x:l)) (True,[]) results = zipWith result result testN True = "ok " ++ show testN result testN False = "nok " ++ show testN Bob -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090221/c1482bc2/attachment-0001.htm From wagner.andrew at gmail.com Sat Feb 21 08:11:16 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Sat Feb 21 08:00:27 2009 Subject: [Haskell-beginners] Help with monads (I think...) In-Reply-To: <3F163140-ACAB-4202-9B98-2269CF2E8A08@gmail.com> References: <3F163140-ACAB-4202-9B98-2269CF2E8A08@gmail.com> Message-ID: Yes, this is much more idiomatic haskell. On Sat, Feb 21, 2009 at 4:59 AM, Thomas Davie wrote: > > On 21 Feb 2009, at 01:30, Patrick LeBoutillier wrote: > > Hi all, > > I'm trying to implement the following simple Perl program in Haskell: > > my $nb_tests = 0 ; > > sub ok { > my $bool = shift ; > $nb_tests++ ; > print STDOUT ($bool ? "ok" : "nok") . " $nb_tests\n" ; > } > > ok(0) ; > ok(1) ; > > The output is: > > nok 1 > ok 2 > > I'm pretty much a Haskell newbie, but I know a bit about monads (and > have been reading "Real World Haskell"), and I think I need to put the > ok function must live inside some kind of state monad. My problem is > that I also would like the ok function to perform some IO (as shown > above, print). > > How is a case like this handled? Can my function live in 2 monads? > > > I personally wouldn't use two monads at all for this ? in fact, I'd only > use IO in one function: > > main = putStr . unlines . results inputs . snd . tests $ inputs > > inputs = [1,2] > > tests = foldr (\_ (x,l) -> (not x, x:l)) (True,[]) > > results = zipWith result > result testN True = "ok " ++ show testN > result testN False = "nok " ++ show testN > > Bob > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090221/c4b40170/attachment.htm From colin at colina.demon.co.uk Sat Feb 21 15:04:21 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Sat Feb 21 14:53:33 2009 Subject: [Haskell-beginners] Baffled by Parsec Message-ID: The tutorials I've found don't tell me what I want to know :-( I have lines that begin with an integer, then white-space, and then further structure to the end-of-line. So for a starter, could you show me how to write a parser for the integer (returning an Int), and how to combine it with a parser for the rest of the line (take that as written - it isn't, but I'll try to do that myself given such a kick-start). Thanks. -- Colin Adams Preston Lancashire From daniel.is.fischer at web.de Sat Feb 21 16:10:36 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sat Feb 21 15:57:05 2009 Subject: [Haskell-beginners] Baffled by Parsec In-Reply-To: References: Message-ID: <200902212210.36616.daniel.is.fischer@web.de> Am Samstag, 21. Februar 2009 21:04 schrieb Colin Paul Adams: > The tutorials I've found don't tell me what I want to know :-( > > I have lines that begin with an integer, then white-space, and then > further structure to the end-of-line. > > So for a starter, could you show me how to write a parser for the > integer (returning an Int), and how to combine it with a parser for > the rest of the line (take that as written - it isn't, but I'll try to > do that myself given such a kick-start). > > Thanks. -- could also be Parser Int, if you don't need user-state parseInt :: GenParser Char st Int parseInt = do neg <- (char '-' >> return True) <|> (optional (char '+') >> return False) digs <- many1 digit let n | neg = negate $ read digs | otherwise = read digs return n parseLine :: GenParser Char st LineStructure parseLine = do -- spaces here, if there may be whitespace at the beginning of lines num <- parseInt spaces things <- parseRemainderOfLine return (combine num things) The strategy is always the same, you write parsers for small things and combine their results. Note that things are somewhat tricky if the structure you want to parse isn't very strict, if one of your possible parsers at some point in the parsing process can fail, but not immediately and you need to backtrack, you have to use the 'try' combinator as in combo = (try parser1) <|> parser2 , but try is bad for performance, so use it only where it's necessary. The latter part is notoriously difficult to identify for the inexperienced, so until you know parsec better, it's okay to insert a few 'try's more than necessary. HTH, otherwise ask again, Daniel From magnus at therning.org Sat Feb 21 16:07:53 2009 From: magnus at therning.org (Magnus Therning) Date: Sat Feb 21 15:57:07 2009 Subject: [Haskell-beginners] Baffled by Parsec In-Reply-To: References: Message-ID: <49A06D29.4050908@therning.org> Colin Paul Adams wrote: > The tutorials I've found don't tell me what I want to know :-( > > I have lines that begin with an integer, then white-space, and then > further structure to the end-of-line. > > So for a starter, could you show me how to write a parser for the > integer (returning an Int), and how to combine it with a parser for > the rest of the line (take that as written - it isn't, but I'll try to > do that myself given such a kick-start). Maybe one of my old blog posts can help? http://therning.org/magnus/archives/289 /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus?therning?org Jabber: magnus?therning?org http://therning.org/magnus identi.ca|twitter: magthe Haskell is an even 'redder' pill than Lisp or Scheme. -- PaulPotts -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 197 bytes Desc: OpenPGP digital signature Url : http://www.haskell.org/pipermail/beginners/attachments/20090221/1ab208fc/signature.bin From keithshep at gmail.com Sat Feb 21 16:35:39 2009 From: keithshep at gmail.com (Keith Sheppard) Date: Sat Feb 21 16:24:49 2009 Subject: [Haskell-beginners] A better way? Message-ID: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> Hello, I'm new to haskell and still getting used to working with lazy evaluation. I created a little function to calculate column widths for a 2D list of strings (a table) by iterating through the list and accumulating a max value for each column. My initial implementation ran out memory for tables with many rows because of lazy evaluation and here is how I dealt with it: {- | for a table, calculate the max width in characters for each column -} maxTableColumnWidths :: [[String]] -> [Int] maxTableColumnWidths [] = [] maxTableColumnWidths table = maxTableColumnWidthsInternal table [] maxTableColumnWidthsInternal :: [[String]] -> [Int] -> [Int] maxTableColumnWidthsInternal [] prevMaxValues = prevMaxValues maxTableColumnWidthsInternal (row:tableTail) prevMaxValues | seqList prevMaxValues = undefined | otherwise = maxTableColumnWidthsInternal tableTail (maxRowFieldWidths row prevMaxValues) -- this little function is for making the list strict... otherwise -- we run out of memory seqList [] = False seqList (head:tail) | head `seq` False = undefined | otherwise = seqList tail maxRowFieldWidths :: [String] -> [Int] -> [Int] maxRowFieldWidths row prevMaxValues = let colLengths = map length row lengthOfRow = length row lengthOfPrevMax = length prevMaxValues maxPrefixList = zipWith max colLengths prevMaxValues in if lengthOfRow == lengthOfPrevMax then maxPrefixList else if lengthOfRow > lengthOfPrevMax then maxPrefixList ++ (drop lengthOfPrevMax colLengths) else maxPrefixList ++ (drop lengthOfRow prevMaxValues) This works but it isn't very pretty (maybe also inefficient?). Is there a better way to deal with this kind of memory issue? Thanks! Keith From tom.davie at gmail.com Sat Feb 21 17:29:35 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Sat Feb 21 17:18:51 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> Message-ID: <28844673-2B37-4640-B081-C9417EC86A10@gmail.com> How about this: maxTableColumnWidths :: [[String]] -> [Int] maxTableColumnWidths = map (maximum . map length) Bob On 21 Feb 2009, at 22:35, Keith Sheppard wrote: > Hello, > > I'm new to haskell and still getting used to working with lazy > evaluation. I created a little function to calculate column widths for > a 2D list of strings (a table) by iterating through the list and > accumulating a max value for each column. My initial implementation > ran out memory for tables with many rows because of lazy evaluation > and here is how I dealt with it: > > {- | > for a table, calculate the max width in characters for each column > -} > maxTableColumnWidths :: [[String]] -> [Int] > maxTableColumnWidths [] = [] > maxTableColumnWidths table = > maxTableColumnWidthsInternal table [] > > maxTableColumnWidthsInternal :: [[String]] -> [Int] -> [Int] > maxTableColumnWidthsInternal [] prevMaxValues = prevMaxValues > maxTableColumnWidthsInternal (row:tableTail) prevMaxValues > | seqList prevMaxValues = undefined > | otherwise = maxTableColumnWidthsInternal tableTail > (maxRowFieldWidths row prevMaxValues) > > -- this little function is for making the list strict... otherwise > -- we run out of memory > seqList [] = False > seqList (head:tail) > | head `seq` False = undefined > | otherwise = seqList tail > > maxRowFieldWidths :: [String] -> [Int] -> [Int] > maxRowFieldWidths row prevMaxValues = > let colLengths = map length row > lengthOfRow = length row > lengthOfPrevMax = length prevMaxValues > maxPrefixList = zipWith max colLengths prevMaxValues > in > if lengthOfRow == lengthOfPrevMax then > maxPrefixList > else if lengthOfRow > lengthOfPrevMax then > maxPrefixList ++ (drop lengthOfPrevMax colLengths) > else > maxPrefixList ++ (drop lengthOfRow prevMaxValues) > > > This works but it isn't very pretty (maybe also inefficient?). Is > there a better way to deal with this kind of memory issue? > > Thanks! > Keith > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners From keithshep at gmail.com Sat Feb 21 17:53:25 2009 From: keithshep at gmail.com (Keith Sheppard) Date: Sat Feb 21 17:42:37 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: <28844673-2B37-4640-B081-C9417EC86A10@gmail.com> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <28844673-2B37-4640-B081-C9417EC86A10@gmail.com> Message-ID: <92e42b740902211453k3f276339n1de23e13860d5bfc@mail.gmail.com> Thank you for the reply, but it looks like this is a different function. Here is the interactive output of my function vs. the one you give (my code is in Table/IO.hs): Prelude> :load Table.IO *Table.IO> maxTableColumnWidths (replicate 10 ["hello", "world"]) [5,5] *Table.IO> let maxTableColumnWidths2 = map (maximum . map length) *Table.IO> maxTableColumnWidths2 (replicate 10 ["hello", "world"]) [5,5,5,5,5,5,5,5,5,5] -Keith On Sat, Feb 21, 2009 at 5:29 PM, Thomas Davie wrote: > How about this: > > maxTableColumnWidths :: [[String]] -> [Int] > maxTableColumnWidths = map (maximum . map length) > > Bob > > > On 21 Feb 2009, at 22:35, Keith Sheppard wrote: > >> Hello, >> >> I'm new to haskell and still getting used to working with lazy >> evaluation. I created a little function to calculate column widths for >> a 2D list of strings (a table) by iterating through the list and >> accumulating a max value for each column. My initial implementation >> ran out memory for tables with many rows because of lazy evaluation >> and here is how I dealt with it: >> >> {- | >> for a table, calculate the max width in characters for each column >> -} >> maxTableColumnWidths :: [[String]] -> [Int] >> maxTableColumnWidths [] = [] >> maxTableColumnWidths table = >> maxTableColumnWidthsInternal table [] >> >> maxTableColumnWidthsInternal :: [[String]] -> [Int] -> [Int] >> maxTableColumnWidthsInternal [] prevMaxValues = prevMaxValues >> maxTableColumnWidthsInternal (row:tableTail) prevMaxValues >> | seqList prevMaxValues = undefined >> | otherwise = maxTableColumnWidthsInternal tableTail >> (maxRowFieldWidths row prevMaxValues) >> >> -- this little function is for making the list strict... otherwise >> -- we run out of memory >> seqList [] = False >> seqList (head:tail) >> | head `seq` False = undefined >> | otherwise = seqList tail >> >> maxRowFieldWidths :: [String] -> [Int] -> [Int] >> maxRowFieldWidths row prevMaxValues = >> let colLengths = map length row >> lengthOfRow = length row >> lengthOfPrevMax = length prevMaxValues >> maxPrefixList = zipWith max colLengths prevMaxValues >> in >> if lengthOfRow == lengthOfPrevMax then >> maxPrefixList >> else if lengthOfRow > lengthOfPrevMax then >> maxPrefixList ++ (drop lengthOfPrevMax colLengths) >> else >> maxPrefixList ++ (drop lengthOfRow prevMaxValues) >> >> >> This works but it isn't very pretty (maybe also inefficient?). Is >> there a better way to deal with this kind of memory issue? >> >> Thanks! >> Keith >> _______________________________________________ >> Beginners mailing list >> Beginners@haskell.org >> http://www.haskell.org/mailman/listinfo/beginners > > From patrick.leboutillier at gmail.com Sat Feb 21 17:54:46 2009 From: patrick.leboutillier at gmail.com (Patrick LeBoutillier) Date: Sat Feb 21 17:43:56 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> Message-ID: Hi, I came up with this, which seems to work well if all your rows have the same number of fields: maxRowFieldWidths :: [[String]] -> [Int] maxRowFieldWidths rows = foldr rowMax zeros rows where rowMax fields maxes = zipWith (\f m -> max (length f) m) fields maxes zeros = 0 : zeros foldr is the key here, which allows you to "accumulate" the results of computations. In this case the accumulator is the list of all the maximums found so far. The initial value for the accumulator is an (infinite) list made up on only zeros. Haskell will generate only as much as it needs. Patrick On Sat, Feb 21, 2009 at 4:35 PM, Keith Sheppard wrote: > Hello, > > I'm new to haskell and still getting used to working with lazy > evaluation. I created a little function to calculate column widths for > a 2D list of strings (a table) by iterating through the list and > accumulating a max value for each column. My initial implementation > ran out memory for tables with many rows because of lazy evaluation > and here is how I dealt with it: > > {- | > for a table, calculate the max width in characters for each column > -} > maxTableColumnWidths :: [[String]] -> [Int] > maxTableColumnWidths [] = [] > maxTableColumnWidths table = > maxTableColumnWidthsInternal table [] > > maxTableColumnWidthsInternal :: [[String]] -> [Int] -> [Int] > maxTableColumnWidthsInternal [] prevMaxValues = prevMaxValues > maxTableColumnWidthsInternal (row:tableTail) prevMaxValues > | seqList prevMaxValues = undefined > | otherwise = maxTableColumnWidthsInternal tableTail > (maxRowFieldWidths row prevMaxValues) > > -- this little function is for making the list strict... otherwise > -- we run out of memory > seqList [] = False > seqList (head:tail) > | head `seq` False = undefined > | otherwise = seqList tail > > maxRowFieldWidths :: [String] -> [Int] -> [Int] > maxRowFieldWidths row prevMaxValues = > let colLengths = map length row > lengthOfRow = length row > lengthOfPrevMax = length prevMaxValues > maxPrefixList = zipWith max colLengths prevMaxValues > in > if lengthOfRow == lengthOfPrevMax then > maxPrefixList > else if lengthOfRow > lengthOfPrevMax then > maxPrefixList ++ (drop lengthOfPrevMax colLengths) > else > maxPrefixList ++ (drop lengthOfRow prevMaxValues) > > > This works but it isn't very pretty (maybe also inefficient?). Is > there a better way to deal with this kind of memory issue? > > Thanks! > Keith > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -- ===================== Patrick LeBoutillier Rosem?re, Qu?bec, Canada From daniel.is.fischer at web.de Sat Feb 21 17:58:41 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sat Feb 21 17:45:08 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: <28844673-2B37-4640-B081-C9417EC86A10@gmail.com> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <28844673-2B37-4640-B081-C9417EC86A10@gmail.com> Message-ID: <200902212358.41220.daniel.is.fischer@web.de> Am Samstag, 21. Februar 2009 23:29 schrieb Thomas Davie: > How about this: > > maxTableColumnWidths :: [[String]] -> [Int] > maxTableColumnWidths = map (maximum . map length) That's not what he needs, maxTableColumnWidths = map (maximum . map length) . transpose would be it. But I'm afraid that wouldn't solve his memory problems. Regarding the memory problems: String is rather a memory hog anyway. Keith, have you considered using ByteStrings? That might solve your memory problems with a straightforward algorithm. Also, if the rows can contain many columns, it is wasteful to calculate the length of prevMaxValues for every row. You could either have that as a parameter, or use a custom zipWith: zipWithD :: (a -> a -> a) -> [a] -> [a] -> [a] zipWithD f (x:xt) (y:yt) = f x y:zipWithD f xt yt zipWithD _ [] ys = ys zipWithD _ xs [] = xs Then maxRowFieldWidths would become maxRowFieldWidths row prev = zipWithD max (map length row) prev or, pointfree: maxRowFieldWidths = zipWithD max . map length seqList can also be written as seqList = foldr seq False That would make maxTableColumnWidths = foldr ((seqList .) . zipWithD max) [] I'm not sure if that is strict enough, though. Also, you might try maxTCWs = foldr seq [] . foldr (zipWithD max) [] , but I expect that to be a bad memory citizen. > > Bob > Cheers, Daniel From daniel.is.fischer at web.de Sat Feb 21 18:16:25 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sat Feb 21 18:02:52 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: <200902212358.41220.daniel.is.fischer@web.de> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <28844673-2B37-4640-B081-C9417EC86A10@gmail.com> <200902212358.41220.daniel.is.fischer@web.de> Message-ID: <200902220016.25290.daniel.is.fischer@web.de> Am Samstag, 21. Februar 2009 23:58 schrieb Daniel Fischer: > Am Samstag, 21. Februar 2009 23:29 schrieb Thomas Davie: > > How about this: > > > > maxTableColumnWidths :: [[String]] -> [Int] > > maxTableColumnWidths = map (maximum . map length) > > That's not what he needs, > > maxTableColumnWidths = map (maximum . map length) . transpose > > would be it. But I'm afraid that wouldn't solve his memory problems. > > Regarding the memory problems: String is rather a memory hog anyway. > Keith, have you considered using ByteStrings? That might solve your memory > problems with a straightforward algorithm. > > Also, if the rows can contain many columns, it is wasteful to calculate the > length of prevMaxValues for every row. You could either have that as a > parameter, or use a custom zipWith: > > zipWithD :: (a -> a -> a) -> [a] -> [a] -> [a] > zipWithD f (x:xt) (y:yt) = f x y:zipWithD f xt yt > zipWithD _ [] ys = ys > zipWithD _ xs [] = xs > > Then maxRowFieldWidths would become > > maxRowFieldWidths row prev = zipWithD max (map length row) prev > > or, pointfree: > > maxRowFieldWidths = zipWithD max . map length > > seqList can also be written as > > seqList = foldr seq False > > That would make > > maxTableColumnWidths = foldr ((seqList .) . zipWithD max) [] Ouch! Of course not seqList, but an analogous function that returns the list itself. evalList xs | seqList xs = undefined | otherwise = xs maxTableColumnWidths = foldr ((evalList .) . zipWithD max) [] > > I'm not sure if that is strict enough, though. > > Also, you might try > > maxTCWs = foldr seq [] . foldr (zipWithD max) [] Oops! No good either. I must be too tired :( maxTCWs = evalList . foldr (zipWithD max) [] > > , but I expect that to be a bad memory citizen. > > > Bob > > Cheers, > Daniel > From daniel.is.fischer at web.de Sat Feb 21 18:21:11 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sat Feb 21 18:07:44 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: <200902220016.25290.daniel.is.fischer@web.de> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <200902212358.41220.daniel.is.fischer@web.de> <200902220016.25290.daniel.is.fischer@web.de> Message-ID: <200902220021.11937.daniel.is.fischer@web.de> Am Sonntag, 22. Februar 2009 00:16 schrieb Daniel Fischer: > > maxTableColumnWidths = foldr ((evalList .) . zipWithD max) [] Oops again: maxTableColumnWidths = foldr ((evalList .) . zipWithD max) [] . map (map length) > > > maxTCWs = evalList . foldr (zipWithD max) [] > maxTCWs = evalList . foldr (zipWithD max) [] . map (map length) > > Cheers, > > Daniel > From keithshep at gmail.com Sat Feb 21 18:52:35 2009 From: keithshep at gmail.com (Keith Sheppard) Date: Sat Feb 21 18:41:45 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> Message-ID: <92e42b740902211552w17734616k5b1e9c3f56936bba@mail.gmail.com> Hello Patrick, I renamed your function maxTableColumnWidths to match up with my naming. It seems to work except that it suffers from the same problem as my 1st implementation when you feed it a table that has many rows: *Table.IO> maxTableColumnWidths (replicate 1000000 ["hello", "world"]) *** Exception: stack overflow Thanks, Keith On Sat, Feb 21, 2009 at 5:54 PM, Patrick LeBoutillier wrote: > Hi, > > I came up with this, which seems to work well if all your rows have > the same number of fields: > > maxRowFieldWidths :: [[String]] -> [Int] > maxRowFieldWidths rows = foldr rowMax zeros rows > where rowMax fields maxes = zipWith (\f m -> max (length f) m) fields maxes > zeros = 0 : zeros > > foldr is the key here, which allows you to "accumulate" the results of > computations. In this case the accumulator is the list of all the > maximums found so far. The initial value for the accumulator is an > (infinite) list made up on only zeros. Haskell will generate only as > much as it needs. > > > Patrick > > > > On Sat, Feb 21, 2009 at 4:35 PM, Keith Sheppard wrote: >> Hello, >> >> I'm new to haskell and still getting used to working with lazy >> evaluation. I created a little function to calculate column widths for >> a 2D list of strings (a table) by iterating through the list and >> accumulating a max value for each column. My initial implementation >> ran out memory for tables with many rows because of lazy evaluation >> and here is how I dealt with it: >> >> {- | >> for a table, calculate the max width in characters for each column >> -} >> maxTableColumnWidths :: [[String]] -> [Int] >> maxTableColumnWidths [] = [] >> maxTableColumnWidths table = >> maxTableColumnWidthsInternal table [] >> >> maxTableColumnWidthsInternal :: [[String]] -> [Int] -> [Int] >> maxTableColumnWidthsInternal [] prevMaxValues = prevMaxValues >> maxTableColumnWidthsInternal (row:tableTail) prevMaxValues >> | seqList prevMaxValues = undefined >> | otherwise = maxTableColumnWidthsInternal tableTail >> (maxRowFieldWidths row prevMaxValues) >> >> -- this little function is for making the list strict... otherwise >> -- we run out of memory >> seqList [] = False >> seqList (head:tail) >> | head `seq` False = undefined >> | otherwise = seqList tail >> >> maxRowFieldWidths :: [String] -> [Int] -> [Int] >> maxRowFieldWidths row prevMaxValues = >> let colLengths = map length row >> lengthOfRow = length row >> lengthOfPrevMax = length prevMaxValues >> maxPrefixList = zipWith max colLengths prevMaxValues >> in >> if lengthOfRow == lengthOfPrevMax then >> maxPrefixList >> else if lengthOfRow > lengthOfPrevMax then >> maxPrefixList ++ (drop lengthOfPrevMax colLengths) >> else >> maxPrefixList ++ (drop lengthOfRow prevMaxValues) >> >> >> This works but it isn't very pretty (maybe also inefficient?). Is >> there a better way to deal with this kind of memory issue? >> >> Thanks! >> Keith >> _______________________________________________ >> Beginners mailing list >> Beginners@haskell.org >> http://www.haskell.org/mailman/listinfo/beginners >> > > > > -- > ===================== > Patrick LeBoutillier > Rosem?re, Qu?bec, Canada > From keithshep at gmail.com Sat Feb 21 19:32:37 2009 From: keithshep at gmail.com (Keith Sheppard) Date: Sat Feb 21 19:21:47 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: <200902220021.11937.daniel.is.fischer@web.de> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <200902212358.41220.daniel.is.fischer@web.de> <200902220016.25290.daniel.is.fischer@web.de> <200902220021.11937.daniel.is.fischer@web.de> Message-ID: <92e42b740902211632k732f0f2ehc2cc2800753934f9@mail.gmail.com> ghci still is not happy if we have many rows... Prelude> :load Table.IO [1 of 1] Compiling Table.IO ( Table/IO.hs, interpreted ) Ok, modules loaded: Table.IO. *Table.IO> let maxTableColumnWidths = foldr ((evalList .) . zipWithD max) [] . map (map length) *Table.IO> let maxTCWs = evalList . foldr (zipWithD max) [] . map (map length) *Table.IO> maxTableColumnWidths (replicate 1000000 ["hello", "world"]) *** Exception: stack overflow *Table.IO> maxTCWs (replicate 1000000 ["hello", "world"]) *** Exception: stack overflow I hadn't thought of using ByteStrings since I don't know what they are :-). I'll have to look into it, but I'm assuming that ByteStrings will give some constant time/space improvement? I think it won't help with my first problem though since what's happening is that the lazy function calls are piling up too deep (at least thats what I think is happening). Thank you Keith On Sat, Feb 21, 2009 at 6:21 PM, Daniel Fischer wrote: > Am Sonntag, 22. Februar 2009 00:16 schrieb Daniel Fischer: >> >> maxTableColumnWidths = foldr ((evalList .) . zipWithD max) [] > > Oops again: > > maxTableColumnWidths = > foldr ((evalList .) . zipWithD max) [] . map (map length) > >> > >> >> maxTCWs = evalList . foldr (zipWithD max) [] >> > > maxTCWs = evalList . foldr (zipWithD max) [] . map (map length) > >> > Cheers, >> > Daniel >> > > From daniel.is.fischer at web.de Sat Feb 21 20:03:30 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sat Feb 21 19:49:57 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: <92e42b740902211632k732f0f2ehc2cc2800753934f9@mail.gmail.com> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <200902220021.11937.daniel.is.fischer@web.de> <92e42b740902211632k732f0f2ehc2cc2800753934f9@mail.gmail.com> Message-ID: <200902220203.30988.daniel.is.fischer@web.de> Am Sonntag, 22. Februar 2009 01:32 schrieb Keith Sheppard: > ghci still is not happy if we have many rows... > > Prelude> :load Table.IO > [1 of 1] Compiling Table.IO ( Table/IO.hs, interpreted ) > Ok, modules loaded: Table.IO. > *Table.IO> let maxTableColumnWidths = foldr ((evalList .) . zipWithD > max) [] . map (map length) > *Table.IO> let maxTCWs = evalList . foldr (zipWithD max) [] . map (map > length) *Table.IO> maxTableColumnWidths (replicate 1000000 ["hello", > "world"]) *** Exception: stack overflow Yes, foldr was the wrong choice. make it foldl' (don't forget the prime at the end) and it works for large tables. If the rows are short, it actually is faster (here) than your version, but if the rows are long , e.g. maxTableColumnWidths (replicate 2000 (replicate 1000 "what?")) your version is faster than import Data.List (foldl') seqList [] = False seqList (head:tail) | head `seq` False = undefined | otherwise = seqList tail evalList xs | seqList xs = undefined | otherwise = xs zipWithD :: (a -> a -> a) -> [a] -> [a] -> [a] zipWithD f (x:xt) (y:yt) = f x y:zipWithD f xt yt zipWithD _ [] ys = ys zipWithD _ xs [] = xs maxTableColumnWidths = foldl' ((evalList .) . zipWithD max) [] . map (map length) > *Table.IO> maxTCWs (replicate 1000000 ["hello", "world"]) > *** Exception: stack overflow That doesn't surprise me in the least. One has to force the list in each step. > > I hadn't thought of using ByteStrings since I don't know what they are ByteStrings are basically byte arrays. Thus if you're dealing exclusively with characters in the range 0-255, you need only one byte per character, while with Strings, you need four bytes for each character itself, plus several machine words for pointers (list cell to Char, list cell to next), I don't remember, but I think it amounts to 12 or 20 bytes per character. > > :-). I'll have to look into it, but I'm assuming that ByteStrings will > > give some constant time/space improvement? Can be several orders of magnitude faster, and as said above, they use far less memory (but they're useful only for long enough strings, having a multitude of short ByteStrings floating around doesn't do any good). > I think it won't help with > my first problem though since what's happening is that the lazy > function calls are piling up too deep (at least thats what I think is > happening). Yes, that's basically what *** Exception: stack overflow means :) > > Thank you > Keith > Cheers, Daniel From matthewjwilliams1 at googlemail.com Sat Feb 21 20:15:30 2009 From: matthewjwilliams1 at googlemail.com (Matthew J. Williams) Date: Sat Feb 21 20:04:29 2009 Subject: [Haskell-beginners] Majority Element Message-ID: <49a0a726.278e420a.6b19.ffffe361@mx.google.com> Dear listers What is a majority element in an array? Sincerely Matthew J. Williams From wagner.andrew at gmail.com Sat Feb 21 20:20:43 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Sat Feb 21 20:09:51 2009 Subject: [Haskell-beginners] Majority Element In-Reply-To: <49a0a726.278e420a.6b19.ffffe361@mx.google.com> References: <49a0a726.278e420a.6b19.ffffe361@mx.google.com> Message-ID: I've never heard this term. Can you give some context? On Sat, Feb 21, 2009 at 8:15 PM, Matthew J. Williams < matthewjwilliams1@googlemail.com> wrote: > Dear listers > > What is a majority element in an array? > > Sincerely > Matthew J. Williams > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090221/ef1e1c3d/attachment.htm From patrick.leboutillier at gmail.com Sat Feb 21 21:32:09 2009 From: patrick.leboutillier at gmail.com (Patrick LeBoutillier) Date: Sat Feb 21 21:21:20 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: <200902220203.30988.daniel.is.fischer@web.de> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <200902220021.11937.daniel.is.fischer@web.de> <92e42b740902211632k732f0f2ehc2cc2800753934f9@mail.gmail.com> <200902220203.30988.daniel.is.fischer@web.de> Message-ID: Hi, I changed my code to : maxTableColumnWidths :: [[String]] -> [Int] maxTableColumnWidths = foldl' rowMax zeros where rowMax = zipWith (\m f -> max (length f) m) zeros = 0 : zeros but it still blows the stack. I don't understand why. Doesn't foldl' force the evaluation of each call to rowMax? If so then I don't see what causes the stack to get so big... unless I'm looking in the wrong place... Can anyone shed some light? Patrick On Sat, Feb 21, 2009 at 8:03 PM, Daniel Fischer wrote: > Am Sonntag, 22. Februar 2009 01:32 schrieb Keith Sheppard: >> ghci still is not happy if we have many rows... >> >> Prelude> :load Table.IO >> [1 of 1] Compiling Table.IO ( Table/IO.hs, interpreted ) >> Ok, modules loaded: Table.IO. >> *Table.IO> let maxTableColumnWidths = foldr ((evalList .) . zipWithD >> max) [] . map (map length) >> *Table.IO> let maxTCWs = evalList . foldr (zipWithD max) [] . map (map >> length) *Table.IO> maxTableColumnWidths (replicate 1000000 ["hello", >> "world"]) *** Exception: stack overflow > > Yes, foldr was the wrong choice. make it foldl' (don't forget the prime at the > end) and it works for large tables. If the rows are short, it actually is > faster (here) than your version, but if the rows are long , e.g. > > maxTableColumnWidths (replicate 2000 (replicate 1000 "what?")) > > your version is faster than > > import Data.List (foldl') > > seqList [] = False > seqList (head:tail) > | head `seq` False = undefined > | otherwise = seqList tail > > evalList xs > | seqList xs = undefined > | otherwise = xs > > zipWithD :: (a -> a -> a) -> [a] -> [a] -> [a] > zipWithD f (x:xt) (y:yt) = f x y:zipWithD f xt yt > zipWithD _ [] ys = ys > zipWithD _ xs [] = xs > > maxTableColumnWidths = > foldl' ((evalList .) . zipWithD max) [] . map (map length) > > >> *Table.IO> maxTCWs (replicate 1000000 ["hello", "world"]) >> *** Exception: stack overflow > > That doesn't surprise me in the least. One has to force the list in each step. > >> >> I hadn't thought of using ByteStrings since I don't know what they are > > ByteStrings are basically byte arrays. Thus if you're dealing exclusively with > characters in the range 0-255, you need only one byte per character, while > with Strings, you need four bytes for each character itself, plus several > machine words for pointers (list cell to Char, list cell to next), I don't > remember, but I think it amounts to 12 or 20 bytes per character. >> >> :-). I'll have to look into it, but I'm assuming that ByteStrings will >> >> give some constant time/space improvement? > > Can be several orders of magnitude faster, and as said above, they use far > less memory (but they're useful only for long enough strings, having a > multitude of short ByteStrings floating around doesn't do any good). > >> I think it won't help with >> my first problem though since what's happening is that the lazy >> function calls are piling up too deep (at least thats what I think is >> happening). > > Yes, that's basically what *** Exception: stack overflow means :) > >> >> Thank you >> Keith >> > > Cheers, > Daniel > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -- ===================== Patrick LeBoutillier Rosem?re, Qu?bec, Canada From keithshep at gmail.com Sat Feb 21 21:38:07 2009 From: keithshep at gmail.com (Keith Sheppard) Date: Sat Feb 21 21:27:16 2009 Subject: [Haskell-beginners] A better way? In-Reply-To: <200902220203.30988.daniel.is.fischer@web.de> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <200902220021.11937.daniel.is.fischer@web.de> <92e42b740902211632k732f0f2ehc2cc2800753934f9@mail.gmail.com> <200902220203.30988.daniel.is.fischer@web.de> Message-ID: <92e42b740902211838m6f119107vdb044b92d0fca4f9@mail.gmail.com> Thanks, this code looks cleaner than what I had. I like how zipWithD fixes the whole issue of uneven rows... -Keith On Sat, Feb 21, 2009 at 8:03 PM, Daniel Fischer wrote: > Am Sonntag, 22. Februar 2009 01:32 schrieb Keith Sheppard: >> ghci still is not happy if we have many rows... >> >> Prelude> :load Table.IO >> [1 of 1] Compiling Table.IO ( Table/IO.hs, interpreted ) >> Ok, modules loaded: Table.IO. >> *Table.IO> let maxTableColumnWidths = foldr ((evalList .) . zipWithD >> max) [] . map (map length) >> *Table.IO> let maxTCWs = evalList . foldr (zipWithD max) [] . map (map >> length) *Table.IO> maxTableColumnWidths (replicate 1000000 ["hello", >> "world"]) *** Exception: stack overflow > > Yes, foldr was the wrong choice. make it foldl' (don't forget the prime at the > end) and it works for large tables. If the rows are short, it actually is > faster (here) than your version, but if the rows are long , e.g. > > maxTableColumnWidths (replicate 2000 (replicate 1000 "what?")) > > your version is faster than > > import Data.List (foldl') > > seqList [] = False > seqList (head:tail) > | head `seq` False = undefined > | otherwise = seqList tail > > evalList xs > | seqList xs = undefined > | otherwise = xs > > zipWithD :: (a -> a -> a) -> [a] -> [a] -> [a] > zipWithD f (x:xt) (y:yt) = f x y:zipWithD f xt yt > zipWithD _ [] ys = ys > zipWithD _ xs [] = xs > > maxTableColumnWidths = > foldl' ((evalList .) . zipWithD max) [] . map (map length) > > >> *Table.IO> maxTCWs (replicate 1000000 ["hello", "world"]) >> *** Exception: stack overflow > > That doesn't surprise me in the least. One has to force the list in each step. > >> >> I hadn't thought of using ByteStrings since I don't know what they are > > ByteStrings are basically byte arrays. Thus if you're dealing exclusively with > characters in the range 0-255, you need only one byte per character, while > with Strings, you need four bytes for each character itself, plus several > machine words for pointers (list cell to Char, list cell to next), I don't > remember, but I think it amounts to 12 or 20 bytes per character. >> >> :-). I'll have to look into it, but I'm assuming that ByteStrings will >> >> give some constant time/space improvement? > > Can be several orders of magnitude faster, and as said above, they use far > less memory (but they're useful only for long enough strings, having a > multitude of short ByteStrings floating around doesn't do any good). > >> I think it won't help with >> my first problem though since what's happening is that the lazy >> function calls are piling up too deep (at least thats what I think is >> happening). > > Yes, that's basically what *** Exception: stack overflow means :) > >> >> Thank you >> Keith >> > > Cheers, > Daniel > > From colin at colina.demon.co.uk Sun Feb 22 02:23:37 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Sun Feb 22 02:12:52 2009 Subject: [Haskell-beginners] Baffled by Parsec In-Reply-To: <200902212210.36616.daniel.is.fischer@web.de> (Daniel Fischer's message of "Sat\, 21 Feb 2009 22\:10\:36 +0100") References: <200902212210.36616.daniel.is.fischer@web.de> Message-ID: >>>>> "Daniel" == Daniel Fischer writes: Thanks. In fact all I need is: parse_integer :: Parser Int parse_integer = do digits <- many1 digit let n = read digits return n as the format does not permit a sign. What I was missing was digits. Where does it come from? I can't find it with Hoggle. -- Colin Adams Preston Lancashire From felipe.lessa at gmail.com Sun Feb 22 02:37:09 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Sun Feb 22 02:26:19 2009 Subject: [Haskell-beginners] Baffled by Parsec In-Reply-To: References: <200902212210.36616.daniel.is.fischer@web.de> Message-ID: On Sun, Feb 22, 2009 at 4:23 AM, Colin Paul Adams wrote: > parse_integer :: Parser Int > parse_integer = do > digits <- many1 digit > let n = read digits > return n 'digits' come from 'digits <- many1 digit', and 'digit' comes from Parsec itself[1] (and is the same as 'satisfy isDigit'[2,3]). I should note that it is more idiomatic to write 'parse_integer' as > import Control.Monad (liftM) > > parse_integer :: Parse Int > parse_integer = read `liftM` many1 digit if you don't need signs. HTH, [1] http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-Parsec-Char.html#v%3Adigit [2] http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/src/Text-Parsec-Char.html#digit [3] http://hackage.haskell.org/packages/archive/base/4.0.0.0/doc/html/Data-Char.html#v%3AisDigit -- Felipe. From colin at colina.demon.co.uk Sun Feb 22 02:50:40 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Sun Feb 22 02:39:51 2009 Subject: [Haskell-beginners] Baffled by Parsec In-Reply-To: (Felipe Lessa's message of "Sun\, 22 Feb 2009 04\:37\:09 -0300") References: <200902212210.36616.daniel.is.fischer@web.de> Message-ID: >>>>> "Felipe" == Felipe Lessa writes: Felipe> On Sun, Feb 22, 2009 at 4:23 AM, Colin Paul Adams Felipe> wrote: >> parse_integer :: Parser Int parse_integer = do digits <- many1 >> digit let n = read digits return n Felipe> 'digits' come from 'digits <- many1 digit', and 'digit' Felipe> comes from Parsec itself[1] (and is the same as 'satisfy Thanks. I meant digit, not digits. Felipe> [1] Felipe> http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-Parsec-Char.html#v%3Adigit OK - I see it here, but I was looking in Text.ParserCombinators.Parsec.Char, where I can't see it (I can see satisfy). I can't see how I am supposed to make that apparently disconnected leap (other than by asking here, which works :-) ) -- Colin Adams Preston Lancashire From felipe.lessa at gmail.com Sun Feb 22 02:53:15 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Sun Feb 22 02:42:23 2009 Subject: [Haskell-beginners] Baffled by Parsec In-Reply-To: References: <200902212210.36616.daniel.is.fischer@web.de> Message-ID: On Sun, Feb 22, 2009 at 4:50 AM, Colin Paul Adams wrote: > OK - I see it here, but I was looking in > Text.ParserCombinators.Parsec.Char, where I can't see it (I can see > satisfy). I can't see how I am supposed to make that apparently > disconnected leap (other than by asking here, which works :-) ) It is there, too! =P http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-ParserCombinators-Parsec-Char.html#v%3Adigit -- Felipe. From colin at colina.demon.co.uk Sun Feb 22 03:02:13 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Sun Feb 22 02:51:24 2009 Subject: [Haskell-beginners] Baffled by Parsec In-Reply-To: (Felipe Lessa's message of "Sun\, 22 Feb 2009 04\:53\:15 -0300") References: <200902212210.36616.daniel.is.fischer@web.de> Message-ID: >>>>> "Felipe" == Felipe Lessa writes: Felipe> On Sun, Feb 22, 2009 at 4:50 AM, Colin Paul Adams Felipe> wrote: >> OK - I see it here, but I was looking in >> Text.ParserCombinators.Parsec.Char, where I can't see it (I can >> see satisfy). I can't see how I am supposed to make that >> apparently disconnected leap (other than by asking here, which >> works :-) ) Felipe> It is there, too! =P Felipe> http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-ParserCombinators-Parsec-Char.html#v%3Adigit Hm. It's not on my local copy of the GHC libraries documentation (ghc 6.10.1), although if I click the source button, I can see it. -- Colin Adams Preston Lancashire From felipe.lessa at gmail.com Sun Feb 22 03:14:25 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Sun Feb 22 03:03:34 2009 Subject: [Haskell-beginners] Baffled by Parsec In-Reply-To: References: <200902212210.36616.daniel.is.fischer@web.de> Message-ID: On Sun, Feb 22, 2009 at 5:02 AM, Colin Paul Adams wrote: > Hm. > > It's not on my local copy of the GHC libraries documentation (ghc > 6.10.1), although if I click the source button, I can see it. My GHC 6.10.1 was compiled from source and Parsec comes from a different ebuild (Gentoo), and digit isn't documented as well. It must be some problem with parsec < 3, because Hackage has the same problem for old Parsec[1]. [1] http://hackage.haskell.org/packages/archive/parsec/2.1.0.1/doc/html/Text-ParserCombinators-Parsec-Char.html -- Felipe. From aslatter at gmail.com Sun Feb 22 03:19:00 2009 From: aslatter at gmail.com (Antoine Latter) Date: Sun Feb 22 03:08:11 2009 Subject: [Haskell-beginners] Baffled by Parsec In-Reply-To: References: <200902212210.36616.daniel.is.fischer@web.de> Message-ID: <694519c50902220019g3c51872dy323dbaeb00fb5767@mail.gmail.com> On Sun, Feb 22, 2009 at 2:14 AM, Felipe Lessa wrote: > > My GHC 6.10.1 was compiled from source and Parsec comes from a > different ebuild (Gentoo), and digit isn't documented as well. It must > be some problem with parsec < 3, because Hackage has the same problem > for old Parsec[1]. > > [1] http://hackage.haskell.org/packages/archive/parsec/2.1.0.1/doc/html/Text-ParserCombinators-Parsec-Char.html > >From the sources: > upper, lower, alphaNum, letter, digit, hexDigit, octDigit :: CharParser st Char I think I've seen Haddock have trouble documenting declarations which share a type signature in other places, as well. Antoine From apfelmus at quantentunnel.de Sun Feb 22 09:30:55 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Sun Feb 22 09:19:21 2009 Subject: [Haskell-beginners] Re: A better way? In-Reply-To: <200902220203.30988.daniel.is.fischer@web.de> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <200902220021.11937.daniel.is.fischer@web.de> <92e42b740902211632k732f0f2ehc2cc2800753934f9@mail.gmail.com> <200902220203.30988.daniel.is.fischer@web.de> Message-ID: Daniel Fischer wrote: > > Yes, foldr was the wrong choice. make it foldl' (don't forget the prime at the > end) and it works for large tables. If the rows are short, it actually is > faster (here) than your version, but if the rows are long , e.g. > > maxTableColumnWidths (replicate 2000 (replicate 1000 "what?")) > > your version is faster than > > import Data.List (foldl') > > seqList [] = False > seqList (head:tail) > | head `seq` False = undefined > | otherwise = seqList tail > > evalList xs > | seqList xs = undefined > | otherwise = xs > > zipWithD :: (a -> a -> a) -> [a] -> [a] -> [a] > zipWithD f (x:xt) (y:yt) = f x y:zipWithD f xt yt > zipWithD _ [] ys = ys > zipWithD _ xs [] = xs > > maxTableColumnWidths = > foldl' ((evalList .) . zipWithD max) [] . map (map length) Nice! I'd use bang patterns in favor of the now outdated | x `seq` False = undefined pattern though. Actually, I'd use import Control.Parallel.Strategies maxWidths = foldl' (\xs ys -> zipWithD max xs ys `using` rnf) [] . map (map length) The module quite useful for controlling evaluation, even when no parallelism is involved. Regards, apfelmus -- http://apfelmus.nfshost.com From apfelmus at quantentunnel.de Sun Feb 22 09:34:49 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Sun Feb 22 09:24:16 2009 Subject: [Haskell-beginners] Re: A better way? In-Reply-To: References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <200902220021.11937.daniel.is.fischer@web.de> <92e42b740902211632k732f0f2ehc2cc2800753934f9@mail.gmail.com> <200902220203.30988.daniel.is.fischer@web.de> Message-ID: Patrick LeBoutillier wrote: > Hi, > > I changed my code to : > > maxTableColumnWidths :: [[String]] -> [Int] > maxTableColumnWidths = foldl' rowMax zeros > where rowMax = zipWith (\m f -> max (length f) m) > zeros = 0 : zeros > > but it still blows the stack. I don't understand why. Doesn't foldl' > force the evaluation of each call to rowMax? If so then I don't see > what causes the stack to get so big... unless I'm looking in the wrong > place... > > Can anyone shed some light? It does force the evaluation of each call to rowMax but only to weak head normal form. In other words, it will only evaluate the list to either a cons cell or an empty list blah ---> blah : blah \-> [] See also http://en.wikibooks.org/wiki/Haskell/Graph_reduction Regards, apfelmus -- http://apfelmus.nfshost.com From daniel.is.fischer at web.de Sun Feb 22 10:17:24 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sun Feb 22 10:03:50 2009 Subject: [Haskell-beginners] Re: A better way? In-Reply-To: References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <200902220203.30988.daniel.is.fischer@web.de> Message-ID: <200902221617.24240.daniel.is.fischer@web.de> Am Sonntag, 22. Februar 2009 15:30 schrieb Heinrich Apfelmus: > Daniel Fischer wrote: > > Yes, foldr was the wrong choice. make it foldl' (don't forget the prime > > at the end) and it works for large tables. If the rows are short, it > > actually is faster (here) than your version, but if the rows are long , > > e.g. > > > > maxTableColumnWidths (replicate 2000 (replicate 1000 "what?")) > > > > your version is faster than > > > > import Data.List (foldl') > > > > seqList [] = False > > seqList (head:tail) > > > > | head `seq` False = undefined > > | otherwise = seqList tail > > > > evalList xs > > > > | seqList xs = undefined > > | otherwise = xs > > > > zipWithD :: (a -> a -> a) -> [a] -> [a] -> [a] > > zipWithD f (x:xt) (y:yt) = f x y:zipWithD f xt yt > > zipWithD _ [] ys = ys > > zipWithD _ xs [] = xs > > > > maxTableColumnWidths = > > foldl' ((evalList .) . zipWithD max) [] . map (map length) > > Nice! I'd use bang patterns in favor of the now outdated > > | x `seq` False = undefined > > pattern though. I would, too, but they're not yet portable, are they? Which implementations other than GHC currently support them? And since seqList was already there, I used that. > > > Actually, I'd use > > import Control.Parallel.Strategies > > maxWidths = foldl' (\xs ys -> zipWithD max xs ys `using` rnf) [] > . map (map length) > > The module quite useful for controlling evaluation, even when no > parallelism is involved. Winner! > > > Regards, > apfelmus > Cheers, Daniel From keithshep at gmail.com Sun Feb 22 11:12:19 2009 From: keithshep at gmail.com (Keith Sheppard) Date: Sun Feb 22 11:01:27 2009 Subject: [Haskell-beginners] Re: Majority Element Message-ID: <92e42b740902220812v57a1d50ah5f1a90220171df92@mail.gmail.com> I think this gets you what you want: majority nums = find (\x -> fromIntegral (length x) > (fromIntegral (length nums)) / 2) (group(sort(nums))) It returns a "Maybe" list containing all majority elements. Something that avoids the sort would be faster though. -Keith > Message: 8 > Date: Sun, 22 Feb 2009 01:15:30 +0000 > From: "Matthew J. Williams" > Subject: [Haskell-beginners] Majority Element > To: beginners@haskell.org > Message-ID: <49a0a726.278e420a.6b19.ffffe361@mx.google.com> > Content-Type: text/plain; charset="us-ascii"; format=flowed > > Dear listers > > What is a majority element in an array? > > Sincerely > Matthew J. Williams > > > > ------------------------------ > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > From daniel.is.fischer at web.de Sun Feb 22 12:39:29 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sun Feb 22 12:25:57 2009 Subject: [Haskell-beginners] Re: Majority Element In-Reply-To: <92e42b740902220812v57a1d50ah5f1a90220171df92@mail.gmail.com> References: <92e42b740902220812v57a1d50ah5f1a90220171df92@mail.gmail.com> Message-ID: <200902221839.30029.daniel.is.fischer@web.de> Am Sonntag, 22. Februar 2009 17:12 schrieb Keith Sheppard: > > Message: 8 > > Date: Sun, 22 Feb 2009 01:15:30 +0000 > > From: "Matthew J. Williams" > > Subject: [Haskell-beginners] Majority Element > > To: beginners@haskell.org > > Message-ID: <49a0a726.278e420a.6b19.ffffe361@mx.google.com> > > Content-Type: text/plain; charset="us-ascii"; format=flowed > > > > Dear listers > > > > What is a majority element in an array? > > > > Sincerely > > Matthew J. Williams > > The answer is implicit in Keith's code below, but let's state it also in plain text: A majority element in a collection C of n things is a value that appears strictly more than n/2 times in C. In general, no majority element exists. I had never met the term before Matthew's post. Does anybody know for what it is important? > I think this gets you what you want: > > majority nums = find (\x -> fromIntegral (length x) > (fromIntegral > (length nums)) / 2) (group(sort(nums))) You don't need the fromIntegral here, integer division does the right thing. In case a majority element a exists, this returns Just [a,a...], so you might add an "fmap head" to get the element itself. > > It returns a "Maybe" list containing all majority elements. Something > that avoids the sort would be faster though. Not the naive algorithm. However, if the type of elements doesn't belong to Ord, we can't use sort :( > > -Keith > findMajority :: Eq a => [a] -> Maybe a findMajority [] = Nothing findMajority xxs@(x:xs) = case sweep x 1 xs of Nothing -> Nothing Just candidate -> verify candidate 0 xxs where sweep a count [] | count == 0 = Nothing | otherwise = Just a sweep _ 0 (y:ys) = sweep y 1 ys sweep a count (y:ys) | a == y = sweep a (count+1) ys | otherwise = sweep a (count-1) ys verify c count (y:ys) | c == y = verify c (count+1) ys | otherwise = verify c (count-1) ys verify c count [] | count > 0 = Just c | otherwise = Nothing Cheers, Daniel From pdr at pdr.cx Fri Feb 20 05:02:03 2009 From: pdr at pdr.cx (Pete Ryland) Date: Mon Feb 23 01:01:06 2009 Subject: [Haskell-beginners] Haskell Tutorial Code Error Message-ID: Hi, Sorry to post to a list, but there are no other contact addresses on the haskell.org site or in the tutorial itself. Any replies, please also CC me as I do not subscribe to any haskell.org lists. I noticed an error in the Haskell Tutorial in section 8.3. The code for the Tree parser will not work. Specifically, the following is broken: readsTree :: (Read a) => ReadS (Tree a) readsTree s = [(Branch l r, x) | ("<", t) <- lex s, (l, u) <- readsTree t, ("|", v) <- lex u, (r, w) <- readsTree v, (">", x) <- lex w ] ++ [(Leaf x, t) | (x, t) <- reads s ] It will not read a string like "<<1|2>|3>" because of the "<<" which the lexer will see as one token. Here is another implementation: showsTree :: (Show a) => Tree a -> ShowS showsTree (Leaf x) = ("Leaf " ++) . shows x showsTree (Branch l r) = ("Branch (" ++) . showsTree l . (") (" ++) . showsTree r . (')':) readsTree :: (Read a) => ReadS (Tree a) readsTree s = [(Branch l r, v) | ("Branch", t) <- lex s, (l, u) <- readsTree t, (r, v) <- readsTree u ] ++ [(Leaf x, u) | ("Leaf", t) <- lex s, (x, u) <- reads t ] ++ [(x, v) | ("(", t) <- lex s, (x, u) <- readsTree t, (")", v) <- lex u ] instance Show a => Show (Tree a) where showsPrec _ x = showsTree x instance Read a => Read (Tree a) where readsPrec _ s = readsTree s This is almost equivalent to the derived one, but will accept strings like "Branch Leaf 3 Branch Branch Leaf 1 Leaf 2 Branch Leaf 5 Leaf 4" (that is, without the parentheses). Regards, Pete From baguasquirrel at gmail.com Fri Feb 20 00:51:06 2009 From: baguasquirrel at gmail.com (Arthur Chan) Date: Mon Feb 23 01:10:25 2009 Subject: [Haskell-beginners] Getting into nested monad transformers Message-ID: <74cabd9e0902192151j23331257vca75c303f624d465@mail.gmail.com> Hey all, I've been trying to access the inner state "s" for this type: newtype TestThingey s a = TestThingey { runTrans :: ReaderT Int (StateT String (StateT s IO)) a } deriving (Monad, MonadIO, MonadState String, MonadReader Int) It doesn't seem to be doable. I could make it into a regular type declaration, but then I lose the GeneralizedNewtypeDeriving. Is this common? Or do people just avoid needing to use "lift"? -Arthur -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090219/fae704c3/attachment-0001.htm From apfelmus at quantentunnel.de Mon Feb 23 05:54:02 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Mon Feb 23 05:42:25 2009 Subject: [Haskell-beginners] Re: A better way? In-Reply-To: <200902221617.24240.daniel.is.fischer@web.de> References: <92e42b740902211335j6866f5b9v6e83ec13343fb7e5@mail.gmail.com> <200902220203.30988.daniel.is.fischer@web.de> <200902221617.24240.daniel.is.fischer@web.de> Message-ID: Daniel Fischer wrote: > >> I'd use bang patterns in favor of the now outdated >> >> | x `seq` False = undefined >> >> pattern though. > > I would, too, but they're not yet portable, are they? > Which implementations other than GHC currently support them? No, they're not portable yet, but they're really convenient. :D The implementations other than GHC will probably pick up -XBangPatterns as well. Regards, apfelmus -- http://apfelmus.nfshost.com From byorgey at seas.upenn.edu Mon Feb 23 06:06:43 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Mon Feb 23 05:55:48 2009 Subject: [Haskell-beginners] Getting into nested monad transformers In-Reply-To: <74cabd9e0902192151j23331257vca75c303f624d465@mail.gmail.com> References: <74cabd9e0902192151j23331257vca75c303f624d465@mail.gmail.com> Message-ID: <20090223110643.GA18439@seas.upenn.edu> On Thu, Feb 19, 2009 at 09:51:06PM -0800, Arthur Chan wrote: > Hey all, > > I've been trying to access the inner state "s" for this type: > > newtype TestThingey s a = TestThingey { > runTrans :: ReaderT Int (StateT String (StateT s IO)) a > } deriving (Monad, MonadIO, MonadState String, MonadReader Int) In this situation I would combine the String and s into one state: ReaderT Int (StateT (String,s) IO) a Otherwise, yes, you'll just have to use the appropriate number of lifts. -Brent From codetojoy at gmail.com Mon Feb 23 09:33:40 2009 From: codetojoy at gmail.com (Michael Easter) Date: Mon Feb 23 09:22:44 2009 Subject: [Haskell-beginners] desugaring an example from RWH Message-ID: <1d393c9d0902230633h19113969t3122cedfc6783328@mail.gmail.com> Folks, I have an example of the do-syntax that I would like to desugar. It is an example from Chapter 28 in RWH. I think I understand the ideas behind the following STM example, but I would like to present it to others in a desugared way: tryBogusSale = do players@(alice:bob:_) <- atomically populateWorld atomically $ alwaysSucceeds =<< consistentBalance players bogusSale Wand 5 alice bob I'm having problems especially with the 2nd line in the do block (i.e. the predicate for alwaysSucceeds). I would like to try and express this in terms of only bind (->) and return. thanks! Michael -- ---------------------- Michael Easter http://codetojoy.blogspot.com: Putting the thrill back in blog http://youtube.com/ocitv -> Fun people doing serious software engineering -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090223/ed207ffd/attachment.htm From wagner.andrew at gmail.com Mon Feb 23 09:40:37 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Mon Feb 23 09:29:43 2009 Subject: [Haskell-beginners] desugaring an example from RWH In-Reply-To: <1d393c9d0902230633h19113969t3122cedfc6783328@mail.gmail.com> References: <1d393c9d0902230633h19113969t3122cedfc6783328@mail.gmail.com> Message-ID: Here's my attempt (without a typechecker):tryBogusSale = atomically populateWorld >>= \players@(alice:bob:_) -> atomically (consistentBalance players >>= alwaysSucceeds) >> bogusSale Wand 5 alice bob On Mon, Feb 23, 2009 at 9:33 AM, Michael Easter wrote: > > Folks, > > I have an example of the do-syntax that I would like to desugar. It is an > example from Chapter 28 in RWH. > > I think I understand the ideas behind the following STM example, but I > would like to present it to others in a desugared way: > > tryBogusSale = do > players@(alice:bob:_) <- atomically populateWorld > atomically $ alwaysSucceeds =<< consistentBalance players > bogusSale Wand 5 alice bob > > I'm having problems especially with the 2nd line in the do block (i.e. the > predicate for alwaysSucceeds). I would like to try and express this in > terms of only bind (->) and return. > > thanks! > Michael > > -- > ---------------------- > Michael Easter > http://codetojoy.blogspot.com: Putting the thrill back in blog > > http://youtube.com/ocitv -> Fun people doing serious software engineering > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090223/9c156025/attachment.htm From codetojoy at gmail.com Mon Feb 23 13:18:19 2009 From: codetojoy at gmail.com (Michael Easter) Date: Mon Feb 23 13:07:23 2009 Subject: [Haskell-beginners] the ($) function (was desugaring an example from RWH) Message-ID: <1d393c9d0902231018n36f4b045se2758ca285787a8@mail.gmail.com> re: desugaring. Thanks Andrew, that worked great! I have another, easier question from the same code in RWH: bogusTransfer qty fromBal toBal = do fromQty <- atomically $ readTVar fromBal [snip] Can someone please explain the ($) function in English? From the type signature, it seems to be an "apply function", but I can't quite explain when we use it. Clearly, it is used throughout RWH but I haven't found a good explanation. My guess is that it is when we want an "execution" of a function rather than a mere reference to it. Is that accurate? thanks again Michael -- ---------------------- Michael Easter http://codetojoy.blogspot.com: Putting the thrill back in blog http://youtube.com/ocitv -> Fun people doing serious software engineering -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090223/12b940d4/attachment.htm From wagner.andrew at gmail.com Mon Feb 23 13:27:01 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Mon Feb 23 13:16:06 2009 Subject: [Haskell-beginners] Re: the ($) function (was desugaring an example from RWH) In-Reply-To: <1d393c9d0902231018n36f4b045se2758ca285787a8@mail.gmail.com> References: <1d393c9d0902231018n36f4b045se2758ca285787a8@mail.gmail.com> Message-ID: The $ function is essentialy a "no-op". That is, it literally does nothing. There is no difference in Haskell between a function and a reference to it. The only purpose of $ is for grouping. The line in question below could have been written identically as "fromQty <- atomically (readTVar fromBal)". The $ groups together everything to the end of the line, and can be used to avoid parentheses that could add noise to the code. On Mon, Feb 23, 2009 at 1:18 PM, Michael Easter wrote: > > re: desugaring. Thanks Andrew, that worked great! > > I have another, easier question from the same code in RWH: > > bogusTransfer qty fromBal toBal = do > fromQty <- atomically $ readTVar fromBal > [snip] > > Can someone please explain the ($) function in English? From the type > signature, it seems to be an "apply function", but I can't quite explain > when we use it. Clearly, it is used throughout RWH but I haven't found a > good explanation. > > My guess is that it is when we want an "execution" of a function rather > than a mere reference to it. Is that accurate? > > thanks again > Michael > > -- > ---------------------- > Michael Easter > http://codetojoy.blogspot.com: Putting the thrill back in blog > > http://youtube.com/ocitv -> Fun people doing serious software engineering > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090223/2834b420/attachment.htm From bugfact at gmail.com Mon Feb 23 14:09:31 2009 From: bugfact at gmail.com (Peter Verswyvelen) Date: Mon Feb 23 13:58:37 2009 Subject: [Haskell-beginners] Re: the ($) function (was desugaring an example from RWH) In-Reply-To: References: <1d393c9d0902231018n36f4b045se2758ca285787a8@mail.gmail.com> Message-ID: Sometimes the apply operator $ can be handy for other purposes too, e.g. map ($ 1) [cos, sin, tan] evaluates to [cos $ 1, sin $ 1, tan $ 1] which just evaluates to [cos 1, sin 1, tan 1] Note that some consider the following as bad coding style: f $ g $ h $ x Instead, the following is preferred f . g . h $ x On Mon, Feb 23, 2009 at 7:27 PM, Andrew Wagner wrote: > The $ function is essentialy a "no-op". That is, it literally does nothing. > There is no difference in Haskell between a function and a reference to it. > The only purpose of $ is for grouping. The line in question below could have > been written identically as "fromQty <- atomically (readTVar fromBal)". The > $ groups together everything to the end of the line, and can be used to > avoid parentheses that could add noise to the code. > > > On Mon, Feb 23, 2009 at 1:18 PM, Michael Easter wrote: > >> >> re: desugaring. Thanks Andrew, that worked great! >> >> I have another, easier question from the same code in RWH: >> >> bogusTransfer qty fromBal toBal = do >> fromQty <- atomically $ readTVar fromBal >> [snip] >> >> Can someone please explain the ($) function in English? From the type >> signature, it seems to be an "apply function", but I can't quite explain >> when we use it. Clearly, it is used throughout RWH but I haven't found a >> good explanation. >> >> My guess is that it is when we want an "execution" of a function rather >> than a mere reference to it. Is that accurate? >> >> thanks again >> Michael >> >> -- >> ---------------------- >> Michael Easter >> http://codetojoy.blogspot.com: Putting the thrill back in blog >> >> http://youtube.com/ocitv -> Fun people doing serious software engineering >> > > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090223/ed10b885/attachment-0001.htm From john.hartnup at gmail.com Mon Feb 23 14:21:06 2009 From: john.hartnup at gmail.com (John Hartnup) Date: Mon Feb 23 14:10:10 2009 Subject: [Haskell-beginners] the ($) function (was desugaring an example from RWH) In-Reply-To: <1d393c9d0902231018n36f4b045se2758ca285787a8@mail.gmail.com> References: <1d393c9d0902231018n36f4b045se2758ca285787a8@mail.gmail.com> Message-ID: <6c1ba2fc0902231121r24ca93eele91a9144a5eff533@mail.gmail.com> I had exactly the same confusion - not explaining ($) in RWH was major dropped ball IMO. > > bogusTransfer qty fromBal toBal = do > fromQty <- atomically $ readTVar fromBal > [snip] > ... is equivalent to: bogusTransfer qty fromBal toBal = do fromQty <- atomically ( readTVar fromBal [snip] ) ... so using ($) prevents accumulating a great big set of parentheses to close at the end of a long block. -- "There is no way to peace; peace is the way" From bbxx789_05ss at yahoo.com Tue Feb 24 02:21:49 2009 From: bbxx789_05ss at yahoo.com (7stud) Date: Tue Feb 24 02:14:07 2009 Subject: [Haskell-beginners] ghc installation on mac osx 10.4.11(intel), Xcode 2.4? Message-ID: Hi, I just bought Real World Haskell, and I'm trying to get the ghc compiler set up. The installer for the latest version of ghc, 6.10.1, is for Leopard(osx 10.5). What should I install for osx 10.4.11(Tiger)? Also, a question about "Beware of enumerating floating point numbers" on p. 11. The book doesn't explain what it means to enumerate floating point numbers without a step, so when it says to beware of the non-intuitive behavior of: ghci> [1.0..1.8] how would a reader know what the intuitive behavior is? Is the step .1, .01, .001? Is there a default step? Who knows? On p. 10 there is an error. Below the last code example on the page, it says: "In the latter case, the list is quite sensibly missing the endpoint of the enumeration, because it isn't an element of the series we defined." But the last line of the code example is this: ghci> [10,9..1] [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] which quite clearly includes both endpoints. From tom.davie at gmail.com Tue Feb 24 02:46:04 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Tue Feb 24 02:35:09 2009 Subject: [Haskell-beginners] ghc installation on mac osx 10.4.11(intel), Xcode 2.4? In-Reply-To: References: Message-ID: <27A817FB-8824-4BAD-A556-8A429339CD06@gmail.com> On 24 Feb 2009, at 08:21, 7stud wrote: > Hi, > > I just bought Real World Haskell, and I'm trying to get the > ghc compiler set up. The installer for the latest version > of ghc, 6.10.1, is for Leopard(osx 10.5). What should > I install for osx 10.4.11(Tiger)? Try using the version in MacPorts. > Also, a question about "Beware of enumerating floating > point numbers" on p. 11. The book doesn't explain > what it means to enumerate floating point numbers > without a step, so when it says to beware of > the non-intuitive behavior of: > > ghci> [1.0..1.8] > > how would a reader know what the intuitive behavior is? > Is the step .1, .01, .001? Is there a default > step? Who knows? I'd say that if you can't figure out what it should do, that's pretty non intuitive, no? Bob From daniel.is.fischer at web.de Tue Feb 24 05:25:53 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Tue Feb 24 05:12:20 2009 Subject: [Haskell-beginners] ghc installation on mac osx 10.4.11(intel), Xcode 2.4? In-Reply-To: References: Message-ID: <200902241125.53452.daniel.is.fischer@web.de> Am Dienstag, 24. Februar 2009 08:21 schrieb 7stud: > Hi, > > Also, a question about "Beware of enumerating floating > point numbers" on p. 11. The book doesn't explain > what it means to enumerate floating point numbers > without a step, so when it says to beware of > the non-intuitive behavior of: > > ghci> [1.0..1.8] > > how would a reader know what the intuitive behavior is? > Is the step .1, .01, .001? Is there a default > step? Who knows? > Experienced Haskellers know :-) The default step is 1, and Prelude> [1.0 .. 1.8] [1.0,2.0] , which is what is meant by "the non-intuitive behaviour". Of course, a learner won't know, so a request to the authors: elaborate that in the second edition. The fact behind it is that [a .. b] is syntactic sugar for enumFromTo a b , enumFromTo is a method in the class Enum. As the name suggests, this class is for types where you can enumerate the elements, every element - except boundary elements - should have a well defined predecessor and successor. So, enumFromTo a b is in these cases the sequence of elements c with index a <= index c <= index b, the indices increasing by 1. This doesn't make much sense for floating point types or Rational, of course. However, arithmetic sequences do make a lot of sense for these types, so they are made instances of the class Enum, too. Since their elements don't have a natural indexing, these instances are by necessity somewhat broken. The enumFrom and enumFromTo methods proceed in steps of 1, which in absence of a reasonable successor function is probably the best choice. However, enumFromTo a b doesn't stop when the value exceeds b, but when it exceeds b+1/2. The behaviour is defined in section 6.3.4 of the Haskell report. > > On p. 10 there is an error. Below the last code example > on the page, it says: > > "In the latter case, the list is quite sensibly missing the > endpoint of the enumeration, because it isn't an > element of the series we defined." > > But the last line of the code example is this: > > ghci> [10,9..1] > [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] > > which quite clearly includes both endpoints. > They probably meant to write [10,8 .. 1]. From rtfm.rtfm.rtfm at gmail.com Tue Feb 24 12:04:33 2009 From: rtfm.rtfm.rtfm at gmail.com (Daneel Yaitskov) Date: Tue Feb 24 11:59:03 2009 Subject: [Haskell-beginners] data constructor with IO type Message-ID: Hi All, I'd like to know does it exist a method which allow to construct the TestB type without a temporary variable such as the TestA constructor. --- module Main where import Monad import Control.Concurrent data TestA = TestA (MVar Bool) xGetA (TestA x) = x data TestB = TestB { xGetB :: MVar Bool } --- main = do tmp <- newMVar False let t = TestB { xGetB = tmp } in do vt <- takeMVar t putStrLn ("HELLO" ++ show vt) --- main = do t <- liftM TestA (newMVar False) vt <- takeMVar (xGetA t) putStrLn ("HELLO" ++ show vt) --- Daneel Yaitskov From byorgey at seas.upenn.edu Tue Feb 24 12:30:23 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Tue Feb 24 12:19:25 2009 Subject: [Haskell-beginners] data constructor with IO type In-Reply-To: References: Message-ID: <20090224173023.GA13417@seas.upenn.edu> On Tue, Feb 24, 2009 at 08:04:33PM +0300, Daneel Yaitskov wrote: > > Hi All, > > I'd like to know does it exist a method which allow to construct the TestB > type without a temporary variable such as the TestA constructor. > > --- > module Main where > > import Monad > import Control.Concurrent > data TestA = TestA (MVar Bool) > xGetA (TestA x) = x > data TestB = TestB { xGetB :: MVar Bool } > > --- > main = > do tmp <- newMVar False > let t = TestB { xGetB = tmp } in > do vt <- takeMVar t > putStrLn ("HELLO" ++ show vt) > --- > > main = do > t <- liftM TestA (newMVar False) > vt <- takeMVar (xGetA t) > putStrLn ("HELLO" ++ show vt) > > --- > > Daneel Yaitskov Hi Daneel, Note that record syntax like > data TestB = TestB { xGetB :: MVar Bool } only adds capabilities; you can still use TestB as if it was defined without record syntax, like TestA. So you are not required to use the TestB {xGetB = tmp} syntax to create a TestB, you could also just say 'TestB tmp'. So the second code example should work fine if you just replace all the 'A's with 'B's. Does this answer your question? I must admit that I am not entirely sure what you are asking, so if this doesn't address your question feel free to clarify. -Brent From bbxx789_05ss at yahoo.com Tue Feb 24 15:16:13 2009 From: bbxx789_05ss at yahoo.com (7stud) Date: Tue Feb 24 15:05:27 2009 Subject: [Haskell-beginners] Re: ghc installation on mac osx 10.4.11(intel), Xcode 2.4? References: <27A817FB-8824-4BAD-A556-8A429339CD06@gmail.com> Message-ID: Thomas Davie gmail.com> writes: > > > On 24 Feb 2009, at 08:21, 7stud wrote: > > > Hi, > > > > I just bought Real World Haskell, and I'm trying to get the > > ghc compiler set up. The installer for the latest version > > of ghc, 6.10.1, is for Leopard(osx 10.5). What should > > I install for osx 10.4.11(Tiger)? > > Try using the version in MacPorts. > I did some more digging around at haskell.org, and I discovered a download for 6.8.2 for mac osx 10.4, so I downloaded and installed that. Will that be ok? For anyone who can't figure out how to install ghc, cd into the ghc folder that is created when you unzip the download. Then read the INSTALL file. To install, I did the following: $ ./configure $ sudo make install At the end of which, I got the message: ----------- Installation of ghc-6.8.2 was successful. To use, add /usr/local/bin to your PATH. Warning: this binary distribution does NOT contain documentation! ----------- > > Also, a question about "Beware of enumerating floating > > point numbers" on p. 11. The book doesn't explain > > what it means to enumerate floating point numbers > > without a step, so when it says to beware of > > the non-intuitive behavior of: > > > > ghci> [1.0..1.8] > > > > how would a reader know what the intuitive behavior is? > > Is the step .1, .01, .001? Is there a default > > step? Who knows? > > I'd say that if you can't figure out what it should do, that's pretty > non intuitive, no? > I would agree. :) From bbxx789_05ss at yahoo.com Tue Feb 24 15:27:20 2009 From: bbxx789_05ss at yahoo.com (7stud) Date: Tue Feb 24 15:16:29 2009 Subject: [Haskell-beginners] Re: ghc installation on mac osx 10.4.11(intel), Xcode 2.4? References: <200902241125.53452.daniel.is.fischer@web.de> Message-ID: Daniel Fischer web.de> writes: > > Experienced Haskellers know > The default step is 1, and > Thanks for the explanation. > > > > But the last line of the code example is this: > > > > ghci> [10,9..1] > > [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] > > > > which quite clearly includes both endpoints. > > > > They probably meant to write > > [10,8 .. 1]. > Actually, after examining the text several more times, the code block has three examples: ghci> [1.0, 1.25..2.0] [1.0,1.25,1.5,1.75,2.0] ghci> [1, 4..15] [1,4,7,10,13] ghci> [10, 9..1] [10,9,8,7,6,5,4,3,2,1] and apparently "In the latter case" was meant to refer to the middle example. From rtfm.rtfm.rtfm at gmail.com Tue Feb 24 16:12:28 2009 From: rtfm.rtfm.rtfm at gmail.com (Daneel Yaitskov) Date: Tue Feb 24 16:03:20 2009 Subject: [Haskell-beginners] Re: data constructor with IO type References: <20090224173023.GA13417@seas.upenn.edu> Message-ID: Brent Yorgey writes: > > Note that record syntax like > >> data TestB = TestB { xGetB :: MVar Bool } > > only adds capabilities; you can still use TestB as if it was defined > without record syntax, like TestA. So you are not required to use the > > TestB {xGetB = tmp} > > syntax to create a TestB, you could also just say 'TestB tmp'. So the > second code example should work fine if you just replace all the 'A's > with 'B's. > > Does this answer your question? I must admit that I am not entirely > sure what you are asking, so if this doesn't address your question > feel free to clarify. > > -Brent I know about it. I mean how to save names of arguments. Because usually data structures is complex and they contain many fields. Method which doesn't the names of the arguments requires to give the values for all members. Sometimes some subsets of one structure calculate themselves at other places or structure contains many fields. One part of them get themselves from the pure functions and other do from the action functions. Daneel Yaitskov From patrick.leboutillier at gmail.com Tue Feb 24 20:32:49 2009 From: patrick.leboutillier at gmail.com (Patrick LeBoutillier) Date: Tue Feb 24 20:21:52 2009 Subject: [Haskell-beginners] Help with TAP implemation in haskell Message-ID: Hi, As a learning exercise, I'm trying to make a Haskell module (my first) that implements a TAP library (http://testanything.org/). The library basically provides some functions to perform unit tests and keeps track of some state. It also performs quite a bit of IO as it goes a long. As a first step I'm loosely basing my code on a Java implementation. You can find the code here: http://svn.solucorp.qc.ca/repos/solucorp/JTap/trunk/JTap.java. I've setup my TapState data structure and a monad transformer to be able to keep state and do IO within the same functions: data TapState = TapState { planSet :: Bool, noPlan :: Bool, skipAll :: Bool, testDied :: Bool, expectedTests :: Int, executedTests :: Int, failedTests :: Int } deriving (Show) type TAP a = StateT TapState IO a In the Java version there is a function called cleanup that is called after all the tests are performed to determine the return code and print some diagnostics: private int cleanup(){ int rc = 0 ; if (! plan_set){ diag("Looks like your test died before it could output anything.") ; return rc ; } if (test_died){ diag("Looks like your test died just after " + executed_tests + ".") ; return rc ; } if ((! skip_all)&&(no_plan)){ print_plan(executed_tests) ; } if ((! no_plan)&&(expected_tests < executed_tests)) { diag("Looks like you planned " + expected_tests + " test" + (expected_tests > 1 ? "s" : "") + " but ran " + (executed_tests - expected_tests) + " extra.") ; rc = -1 ; } if ((! no_plan)&&(expected_tests > executed_tests)) { diag("Looks like you planned " + expected_tests + " test" + (expected_tests > 1 ? "s" : "") + " but only ran " + executed_tests + ".") ; } if (failed_tests > 0){ diag("Looks like you failed " + failed_tests + " test" + (failed_tests > 1 ? "s" : "") + " of " + executed_tests + ".") ; } return rc ; } I'm having problems implementing the equivalent of this function in haskell. Inside a do block, is there a way to terminate the function immediately and return a result ("return" in the imperative sense, not the Haskell sense)? If not, must one really use deeply nested if/then/else statements to treat these special cases? All I could come up was this, which I find quite ugly: _cleanup :: Int -> TAP Int _cleanup rc = do ts <- get if (not $ planSet ts) then do diag "Looks like your test died before it could output anything." return rc else if (testDied ts) then do diag $ "Looks like your test died just after " ++ (show $ executedTests ts) return rc else ... Thanks a lot, Patrick Note: If it helps, you can find my Haskell code here: http://svn.solucorp.qc.ca/repos/solucorp/JTap/trunk/tap.hs -- ===================== Patrick LeBoutillier Rosem?re, Qu?bec, Canada From gtener at gmail.com Tue Feb 24 21:07:09 2009 From: gtener at gmail.com (=?UTF-8?Q?Krzysztof_Skrz=C4=99tnicki?=) Date: Tue Feb 24 20:56:10 2009 Subject: [Haskell-beginners] Help with TAP implemation in haskell In-Reply-To: References: Message-ID: <220e47b40902241807t3e23ba63o40f22be9fb1f491f@mail.gmail.com> On Wed, Feb 25, 2009 at 02:32, Patrick LeBoutillier wrote: > I'm having problems implementing the equivalent of this function in > haskell. Inside a do block, is there a way to terminate the function > immediately and return a result ("return" in the imperative sense, not > the Haskell sense)? If not, must one really use deeply nested > if/then/else statements to treat these special cases? All I could come > up was this, which I find quite ugly: For complex control flow continuation monad can be quite useful. But one must be careful not to abuse it. Code with heavy use of continuations can be very hard to follow and hard to debug as well. Here is an example: module Main where import Control.Monad.Cont checkErrors :: Int -> Maybe String checkErrors ident = (`runCont` id) $ do response <- callCC $ \exit -> do when (ident == 1) (exit . Just $ "Error! 1!") when (ident == 2) (exit . Just $ "Error! 2!") when (ident == 3) (exit . Just $ "Error! 3!") when (ident == 4) (exit . Just $ "Error! 4!") when (ident == 5) (exit . Just $ "Error! 5!") return Nothing return response main = forever $ getLine >>= \n -> print (checkErrors (read n)) It runs : $ ./callcc 0 Nothing 1 Just "Error! 1!" 5 Just "Error! 5!" 3 Just "Error! 3!" 2 Just "Error! 2!" 1 Just "Error! 1!" 9 Nothing 8 Nothing ^C Please read documentation on Control.Monad.Cont. There are more elaborate explanations there. All best Christopher Skrz?tnicki From felipe.lessa at gmail.com Tue Feb 24 21:38:42 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Tue Feb 24 21:27:43 2009 Subject: [Haskell-beginners] Help with TAP implemation in haskell In-Reply-To: References: Message-ID: On Tue, Feb 24, 2009 at 10:32 PM, Patrick LeBoutillier wrote: > _cleanup :: Int -> TAP Int > _cleanup rc = do > ? ?ts <- get > ? ?if (not $ planSet ts) > ? ? ? ?then do > ? ? ? ? ? ?diag "Looks like your test died before it could output anything." > ? ? ? ? ? ?return rc > ? ? ? ?else if (testDied ts) > ? ? ? ? ? ?then do > ? ? ? ? ? ? ? ?diag $ "Looks like your test died just after " ++ > (show $ executedTests ts) > ? ? ? ? ? ? ? ?return rc > ? ? ? ? ? ?else ... _cleanup rc = do ts <- get let err | not (planSet ts) = diag "Looks like...anything." | testDied ts = diag $ "Looks like...after " ++ show (executedTests ts) | otherwise = return () -- assuming diag :: String -> TAP () err >> return rc or maybe _cleanup rc = get >>= showErrs >> return rc where showErrs ts | not (planSet ts) = diag "Looks like...anything." | testDied ts = diag $ "Looks like...after " ++ show (executedTests ts) | otherwise = return () HTH, -- Felipe. From allbery at ece.cmu.edu Tue Feb 24 21:42:09 2009 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Tue Feb 24 21:31:29 2009 Subject: [Haskell-beginners] Help with TAP implemation in haskell In-Reply-To: References: Message-ID: On 2009 Feb 24, at 20:32, Patrick LeBoutillier wrote: > I'm having problems implementing the equivalent of this function in > haskell. Inside a do block, is there a way to terminate the function > immediately and return a result ("return" in the imperative sense, not Take a look at MonadCont. But cleaner is to use Maybe (or MaybeT from Hackage): > -- you don't need to define this, it's in the Prelude > instance Monad Maybe where > return = Just > Nothing >>= _ = Nothing > (Just x) >>= f = f x So if a test produces Nothing, you short-circuit past the remaining tests in the (>>=)-chain. But since you need to propagate the TAP state even when you are given Nothing, you want to wrap the Maybe in a StateT (and since you have IO at the bottom, you need MaybeT from Hackage): > type TAP a = StateT TAPState (MaybeT IO a) BTW, are you integrating this with QuickCheck and/or SmallCheck? It might be nice to have > withTAPplan myPlan $ do > qTAP propertyOne -- Test.QuickCheck.quickCheck > sTAP propertyTwo -- Test.SmallCheck.test > sTAPToDepth 5 property3 -- Test.SmallCheck.smallCheck > -- need wrappers because e.g. quickCheck won't expect a TAPState passed in > -- or you could define (>>=) in your monad to DTRT Also, in Haskell it is preferable to stay pure, perhaps especially while testing, so I would ditch the IO in the default case and provide a secondary function for tests that require IO. (hm, I sure hope I got this right, since my sinuses are trying to squeeze my brain out my ears...) -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 195 bytes Desc: This is a digitally signed message part Url : http://www.haskell.org/pipermail/beginners/attachments/20090224/3b85e11e/PGP.bin From pscott at foo.me.uk Wed Feb 25 19:18:15 2009 From: pscott at foo.me.uk (Philip Scott) Date: Wed Feb 25 23:15:55 2009 Subject: [Haskell-beginners] Defeating type inference Message-ID: <49A5DFC7.10507@foo.me.uk> Well, either that or I being an idiot. Here's a little example. Let us say you had a datatype 'Month'* data Month = Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec deriving(Show, Eq, Ord, Ix) What I would like to make is an infinite lazy list of months (called, rather imaginitively I thought, 'months') that keeps wrapping around. That is to say, it would make a list like this [Jan, Feb, ...., Nov, Dec, Jan, Feb, ....., Nov, Dec, ... ad infinitum ] I am sure you get the picture. My first stab was this: months = range (Jan, Dec) : months But of course, what you get here is a list of lists, with each element being a list of [Jan, Feb, ...., Dec] So I puzzled for a little bit about how to do this in the most Haskelly way and I thought of this months = concat (range (Jan, Dec) : months) Which should work, right** But the type checker is not pleased at all and complains: Couldn't match expected type `[Month]' against inferred type `Month' Expected type: [[Month]] Inferred type: [Month] In the expression: concat (range (Jan, Dec) : months) In the definition of `months': months = concat (range (Jan, Dec) : months) However, if you use the first definition and make a second function: months = range (Jan, Dec) : months realmonths = concat(months) It is happy and does what one might expect. I thought perhaps I was just confusing the inference engine so I tried a liberal sprinkling of :: operators to make my intentions clear, but it still wasn't having any of it. Any thoughts welcomed! - Philip * I am aware that there is plenty of code to handle dates and times already written, probably much more nicely than mine - this is just a project I have been hacking at to get to grips with things. ** though I am pretty sure this is the Wrong Way to do this. I suspect concat takes O(n) time - more elegant approaches would be welcomed! From aslatter at gmail.com Wed Feb 25 23:41:23 2009 From: aslatter at gmail.com (Antoine Latter) Date: Wed Feb 25 23:30:19 2009 Subject: [Haskell-beginners] Defeating type inference In-Reply-To: <49A5DFC7.10507@foo.me.uk> References: <49A5DFC7.10507@foo.me.uk> Message-ID: <694519c50902252041k4fc23804gcf8a86a35d017df6@mail.gmail.com> On Wed, Feb 25, 2009 at 6:18 PM, Philip Scott wrote: > Well, either that or I being an idiot. > > Here's a little example. Let us say you had a datatype 'Month'* > > data Month = Jan > ? ? ?| ? ? Feb > ? ? ?| ? ? Mar > ? ? ?| ? ? Apr > ? ? ?| ? ? May > ? ? ?| ? ? Jun > ? ? ?| ? ? Jul > ? ? ?| ? ? Aug > ? ? ?| ? ? Sep > ? ? ?| ? ? Oct > ? ? ?| ? ? Nov > ? ? ?| ? ? Dec > ? ? ?deriving(Show, Eq, Ord, Ix) > months = concat (range (Jan, Dec) : months) > > Which should work, right** > > But the type checker is not pleased at all and complains: > > ? ? ? Couldn't match expected type `[Month]' > ? ? ? ? ? ? ?against inferred type `Month' > ? ? ? ? Expected type: [[Month]] > ? ? ? ? Inferred type: [Month] > ? ? ? In the expression: concat (range (Jan, Dec) : months) > ? ? ? In the definition of `months': > ? ? ? ? ? months = concat (range (Jan, Dec) : months) > > However, if you use the first definition and make a second function: > > months = range (Jan, Dec) : months > realmonths = concat(months) > > It is happy and does what one might expect. I thought perhaps I was just > confusing the inference engine so I tried a liberal sprinkling of :: > operators to make my intentions clear, but it still wasn't having any of it. > Can you post your version of the problem function which includes type signatures? Can you also write-out a top-level type signature for the entire expression? Antoine From alexander.dunlap at gmail.com Thu Feb 26 00:05:12 2009 From: alexander.dunlap at gmail.com (Alexander Dunlap) Date: Wed Feb 25 23:54:09 2009 Subject: [Haskell-beginners] Defeating type inference In-Reply-To: <49A5DFC7.10507@foo.me.uk> References: <49A5DFC7.10507@foo.me.uk> Message-ID: <57526e770902252105r5412814dx1f6130453f58fe07@mail.gmail.com> On Wed, Feb 25, 2009 at 4:18 PM, Philip Scott wrote: > months = range (Jan, Dec) : months > > But of course, what you get here is a list of lists, with each element being > a list of [Jan, Feb, ...., Dec] > > So I puzzled for a little bit about how to do this in the most Haskelly way > and I thought of this > > months = concat (range (Jan, Dec) : months) > > Which should work, right** > > But the type checker is not pleased at all and complains: > > ? ? ? Couldn't match expected type `[Month]' > ? ? ? ? ? ? ?against inferred type `Month' > ? ? ? ? Expected type: [[Month]] > ? ? ? ? Inferred type: [Month] > ? ? ? In the expression: concat (range (Jan, Dec) : months) > ? ? ? In the definition of `months': > ? ? ? ? ? months = concat (range (Jan, Dec) : months) > > However, if you use the first definition and make a second function: > > months = range (Jan, Dec) : months > realmonths = concat(months) > The problem is that when you go from > months = range (Jan,Dec) : months > realmonths = concat months to > months = concat (range (Jan,Dec) : months) you're not just collapsing the two functions, you're changing the definition (and type!) of "months" which you referred to within the months function. Since months is a recursive function, you can't necessary fold in the definition of realmonths because you want the recursion to apply to the original months, not the original realmonths. As you suspected, there are better and simpler ways of doing this available, although your way is good for getting the hang of recursion, even though experienced haskellers really don't use recursion all that much. (Most prefer to use functions that encapsulate recursion *patterns* such as map, filter, folds and many more.) You could use list concatentation while keeping the recursion, as in > months = range (Jan,Dec) ++ months Even better, import Data.List and use the built-in cycle function (http://www.haskell.org/ghc/dist/current/docs/libraries/base/Data-List.html#v%3Acycle): > months = cycle (range (Jan,Dec)) Hope that helps. Alex From rtfm.rtfm.rtfm at gmail.com Thu Feb 26 03:02:39 2009 From: rtfm.rtfm.rtfm at gmail.com (Daneel Yaitskov) Date: Thu Feb 26 02:53:14 2009 Subject: [Haskell-beginners] how to instance a class Message-ID: Hi, I study opengl and decided to improve the Vertex3 type. data Vertex3 a => Vertex3 a! a! a! a vertex and a vector are same. It is often need to multiple a vector at a scalar or to calculate a scalar production of two vectors. I have realized the Num class for the Vertex3 type: instance (Num a) => Num (Vertex3 a) where (Vertex3 x y z) * (Vertex3 x' y' z') = (Vertex3 (x*x') (y*y') (z*z')) (Vertex3 x y z) + (Vertex3 x' y' z') = (Vertex3 (x+x') (y+y') (z+z')) (Vertex3 x y z) - (Vertex3 x' y' z') = (Vertex3 (x-x') (y-y') (z-z')) abs (Vertex3 x y z) = (Vertex3 (abs x) (abs y) (abs z)) signum (Vertex3 x y z) = (Vertex3 (signum x) (signum y) (signum z)) negate (Vertex3 x y z) = (Vertex3 (-x) (-y) (-z)) instance (Fractional a) => Fractional (Vertex3 a) where (Vertex3 x y z) / (Vertex3 x' y' z') = (Vertex3 (x/x') (y/y') (z/z')) -------------- But I can't instance my own class: class (Num a) => SVect a where (***) :: Num b => a -> b -> a instance (Num t) => SVect (Vertex3 t) where (Vertex3 x y z) *** c = Vertex3 (c*x) (c*y) (c*z) GHC posts about the error: surface.hs:107:36: Couldn't match expected type `b' against inferred type `t' `b' is a rigid type variable bound by the type signature for `***' at surface.hs:103:14 `t' is a rigid type variable bound by the instance declaration at surface.hs:105:14 In the second argument of `(*)', namely `x' In the first argument of `Vertex3', namely `(c * x)' In the expression: Vertex3 (c * x) (c * y) (c * z) ------------------------ I understand the "c" argument must have type as x,y and z, but I don't know what need to do. Daneel Yaitskov. From tom.davie at gmail.com Thu Feb 26 03:12:54 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Feb 26 03:01:54 2009 Subject: [Haskell-beginners] how to instance a class In-Reply-To: References: Message-ID: <92E9CF39-1898-4825-9B9C-7EF59822520B@gmail.com> On 26 Feb 2009, at 09:02, Daneel Yaitskov wrote: > -------------- > But I can't instance my own class: > > class (Num a) => SVect a where > (***) :: Num b => a -> b -> a > > instance (Num t) => SVect (Vertex3 t) where > (Vertex3 x y z) *** c = Vertex3 (c*x) (c*y) (c*z) > > GHC posts about the error: > > surface.hs:107:36: > Couldn't match expected type `b' against inferred type `t' > `b' is a rigid type variable bound by > the type signature for `***' at surface.hs:103:14 > `t' is a rigid type variable bound by > the instance declaration at surface.hs:105:14 > In the second argument of `(*)', namely `x' > In the first argument of `Vertex3', namely `(c * x)' > In the expression: Vertex3 (c * x) (c * y) (c * z) > ------------------------ > > I understand the "c" argument must have type as x,y and z, but > I don't know what need to do. I don't immediately see what is causing your error, but try downloading the VectorSpace package off hackage ? it may save you a lot of wheel reinventing here. Bob From daniel.is.fischer at web.de Thu Feb 26 05:09:44 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Feb 26 04:58:43 2009 Subject: [Haskell-beginners] Defeating type inference In-Reply-To: <57526e770902252105r5412814dx1f6130453f58fe07@mail.gmail.com> References: <49A5DFC7.10507@foo.me.uk> <57526e770902252105r5412814dx1f6130453f58fe07@mail.gmail.com> Message-ID: <200902261109.44223.daniel.is.fischer@web.de> Am Donnerstag, 26. Februar 2009 06:05 schrieb Alexander Dunlap: > On Wed, Feb 25, 2009 at 4:18 PM, Philip Scott wrote: > > months = range (Jan, Dec) : months > > > > But of course, what you get here is a list of lists, with each element > > being a list of [Jan, Feb, ...., Dec] > > > > So I puzzled for a little bit about how to do this in the most Haskelly > > way and I thought of this > > > > months = concat (range (Jan, Dec) : months) > > > > Which should work, right** > > > > But the type checker is not pleased at all and complains: > > > > Couldn't match expected type `[Month]' > > against inferred type `Month' > > Expected type: [[Month]] > > Inferred type: [Month] > > In the expression: concat (range (Jan, Dec) : months) > > In the definition of `months': > > months = concat (range (Jan, Dec) : months) > > > > However, if you use the first definition and make a second function: > > > > months = range (Jan, Dec) : months > > realmonths = concat(months) > > The problem is that when you go from > > > months = range (Jan,Dec) : months > > realmonths = concat months > > to > > > months = concat (range (Jan,Dec) : months) > > you're not just collapsing the two functions, you're changing the > definition (and type!) of "months" which you referred to within the > months function. Since months is a recursive function, you can't > necessary fold in the definition of realmonths because you want the > recursion to apply to the original months, not the original > realmonths. > > As you suspected, there are better and simpler ways of doing this > available, although your way is good for getting the hang of > recursion, even though experienced haskellers really don't use > recursion all that much. (Most prefer to use functions that > encapsulate recursion *patterns* such as map, filter, folds and many > more.) You could use list concatentation while keeping the recursion, > as in > > > months = range (Jan,Dec) ++ months > > Even better, import Data.List and use the built-in cycle function > > (http://www.haskell.org/ghc/dist/current/docs/libraries/base/Data-List.html#v%3Acycle): > > months = cycle (range (Jan,Dec)) One more improvement, include also Enum among the derived classes, then you can write months = cycle [Jan .. Dec] Oh, and cycle is also exported from the Prelude, so it's not necessary to import Data.List for that (though you will probably want to imoprt it anyway). > > Hope that helps. > > Alex Cheers, Daniel From daniel.is.fischer at web.de Thu Feb 26 05:30:47 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Feb 26 05:19:46 2009 Subject: [Haskell-beginners] how to instance a class In-Reply-To: <92E9CF39-1898-4825-9B9C-7EF59822520B@gmail.com> References: <92E9CF39-1898-4825-9B9C-7EF59822520B@gmail.com> Message-ID: <200902261130.47345.daniel.is.fischer@web.de> Am Donnerstag, 26. Februar 2009 09:12 schrieb Thomas Davie: > On 26 Feb 2009, at 09:02, Daneel Yaitskov wrote: > > -------------- > > But I can't instance my own class: > > > > class (Num a) => SVect a where > > (***) :: Num b => a -> b -> a > > > > instance (Num t) => SVect (Vertex3 t) where > > (Vertex3 x y z) *** c = Vertex3 (c*x) (c*y) (c*z) > > > > GHC posts about the error: > > > > surface.hs:107:36: > > Couldn't match expected type `b' against inferred type `t' > > `b' is a rigid type variable bound by > > the type signature for `***' at surface.hs:103:14 > > `t' is a rigid type variable bound by > > the instance declaration at surface.hs:105:14 > > In the second argument of `(*)', namely `x' > > In the first argument of `Vertex3', namely `(c * x)' > > In the expression: Vertex3 (c * x) (c * y) (c * z) > > ------------------------ > > > > I understand the "c" argument must have type as x,y and z, but > > I don't know what need to do. The problem is that the type signature of (***) promises that it works with *any* Num type, so if v :: Vertex3 Int and c :: Double, v *** c should work. Or if v :: Vertex3 Double, c :: Complex Float, it should work, too. It obviously can't work by simply multiplying every component of v with c. But what you want isn't that general, what you want is that for every vector type a, there is some number type b, *depending on a*, for which (***) is defined. The solution to the problem is a) multiparameter typeclasses (MPTCs) b) functional dependencies (FunDeps) c) flexible instances {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-} data Vec c = V !c !c deriving (Eq, Show) instance (Num c) => Num (Vec c) where (V x y) + (V u v) = V (x+u) (y+v) (V x y) - (V u v) = V (x-u) (y-v) -- I omit the others for brevity -- the SVec type class for a type a of vectors and a type b of scalars -- the type of scalars is uniquely determined by the vector type, -- that is what the "| a -> b" in the class declaration means class (Num a, Num b) => SVec a b | a -> b where (***) :: a -> b -> a -- since the type variable c appears twice in this instance declaration, -- we need the FlexibleInstances extension instance Num c => SVec (Vec c) c where (V x y) *** t = V (t*x) (t*y) > > I don't immediately see what is causing your error, but try > downloading the VectorSpace package off hackage ? it may save you a > lot of wheel reinventing here. > That is probably a good idea. While it is instructive to roll your own, avoiding reinvention of wheels is a good thing (and you can compare your wheel with the other, too). Cheers, Daniel From mle+cl at mega-nerd.com Thu Feb 26 05:42:40 2009 From: mle+cl at mega-nerd.com (Erik de Castro Lopo) Date: Thu Feb 26 05:31:41 2009 Subject: [Haskell-beginners] Meaning of '!' in record defintion? UNPACK? Message-ID: <20090226214240.2c774606.mle+cl@mega-nerd.com> Hi all, I'm looking at some code that defines a record: data Position = Position { posOffset :: {-# UNPACK #-} !Int , posRow :: {-# UNPACK #-} !Int , posColumn :: {-# UNPACK #-} !Int } What does the the exclamation mark mean? And UNPACK? Thanks in advance. Cheers, Erik -- ----------------------------------------------------------------- Erik de Castro Lopo ----------------------------------------------------------------- Microsoft is finally bringing all of its Windows operating system families under one roof. It will combine all of the features of CE, stability and support of ME and the speed of NT. It will be called Windows CEMENT... From tom.davie at gmail.com Thu Feb 26 05:48:09 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Feb 26 05:37:06 2009 Subject: [Haskell-beginners] Meaning of '!' in record defintion? UNPACK? In-Reply-To: <20090226214240.2c774606.mle+cl@mega-nerd.com> References: <20090226214240.2c774606.mle+cl@mega-nerd.com> Message-ID: <9540020A-ECB1-4A6D-8808-E25F227F9B6D@gmail.com> On 26 Feb 2009, at 11:42, Erik de Castro Lopo wrote: > Hi all, > > I'm looking at some code that defines a record: > > data Position = > Position { posOffset :: {-# UNPACK #-} !Int > , posRow :: {-# UNPACK #-} !Int > , posColumn :: {-# UNPACK #-} !Int > } > > What does the the exclamation mark mean? And UNPACK? The ! means "strict" ? i.e. don't store a thunk for an Int here, but evaluate it first. The {-# UNPACK #-} tells the compiler that it can unpack the Int ? meaning that a Position will be neatly packed into 12 bytes. Bob From colin at colina.demon.co.uk Thu Feb 26 06:07:31 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Thu Feb 26 05:56:30 2009 Subject: [Haskell-beginners] Meaning of '!' in record defintion? UNPACK? In-Reply-To: <9540020A-ECB1-4A6D-8808-E25F227F9B6D@gmail.com> (Thomas Davie's message of "Thu\, 26 Feb 2009 11\:48\:09 +0100") References: <20090226214240.2c774606.mle+cl@mega-nerd.com> <9540020A-ECB1-4A6D-8808-E25F227F9B6D@gmail.com> Message-ID: >>>>> "Thomas" == Thomas Davie writes: Thomas> The {-# UNPACK #-} tells the compiler that it can unpack Thomas> the Int ? meaning that a Position will be neatly packed Thomas> into 12 bytes. What would be the difference if there was no UNPACK pragma? -- Colin Adams Preston Lancashire From tom.davie at gmail.com Thu Feb 26 06:23:17 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Feb 26 06:12:14 2009 Subject: [Haskell-beginners] Meaning of '!' in record defintion? UNPACK? In-Reply-To: References: <20090226214240.2c774606.mle+cl@mega-nerd.com> <9540020A-ECB1-4A6D-8808-E25F227F9B6D@gmail.com> Message-ID: <4F0DF84C-C028-4883-8CC0-AC14C0C69F97@gmail.com> On 26 Feb 2009, at 12:07, Colin Paul Adams wrote: >>>>>> "Thomas" == Thomas Davie writes: > > Thomas> The {-# UNPACK #-} tells the compiler that it can unpack > Thomas> the Int ? meaning that a Position will be neatly packed > Thomas> into 12 bytes. > > What would be the difference if there was no UNPACK pragma? The tag in the Ints would be included in the structure created, with UNPACK, they would not. Bob From colin at colina.demon.co.uk Thu Feb 26 06:29:48 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Thu Feb 26 06:18:49 2009 Subject: [Haskell-beginners] Meaning of '!' in record defintion? UNPACK? In-Reply-To: <4F0DF84C-C028-4883-8CC0-AC14C0C69F97@gmail.com> (Thomas Davie's message of "Thu\, 26 Feb 2009 12\:23\:17 +0100") References: <20090226214240.2c774606.mle+cl@mega-nerd.com> <9540020A-ECB1-4A6D-8808-E25F227F9B6D@gmail.com> <4F0DF84C-C028-4883-8CC0-AC14C0C69F97@gmail.com> Message-ID: >>>>> "Thomas" == Thomas Davie writes: Thomas> On 26 Feb 2009, at 12:07, Colin Paul Adams wrote: >>>>>> "Thomas" == Thomas Davie writes: >> Thomas> The {-# UNPACK #-} tells the compiler that it can unpack Thomas> the Int ? meaning that a Position will be neatly packed Thomas> into 12 bytes. >> >> What would be the difference if there was no UNPACK pragma? Thomas> The tag in the Ints would be included in the structure Thomas> created, with UNPACK, they would not. What is the tag? -- Colin Adams Preston Lancashire From felipe.lessa at gmail.com Thu Feb 26 06:30:27 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Thu Feb 26 06:19:22 2009 Subject: [Haskell-beginners] Meaning of '!' in record defintion? UNPACK? In-Reply-To: References: <20090226214240.2c774606.mle+cl@mega-nerd.com> <9540020A-ECB1-4A6D-8808-E25F227F9B6D@gmail.com> Message-ID: On Thu, Feb 26, 2009 at 8:07 AM, Colin Paul Adams wrote: >>>>>> "Thomas" == Thomas Davie writes: > > ? ?Thomas> The {-# UNPACK #-} tells the compiler that it can unpack > ? ?Thomas> the Int ? meaning that a Position will be neatly packed > ? ?Thomas> into 12 bytes. > > What would be the difference if there was no UNPACK pragma? For example, if you write valid :: Position -> Bool valid (Position o r c) = o < r && c < 80 It is just an example, not necessarily meaningful :). If you use the UNPACK pragmas, then internally the compiler will create something like valid :: Int# -> Int# -> Int# -> Bool valid o r c = o <# r && c <# 80 Basically the three integers will be passed on registers. Without the UNPACK, they would be passed on the heap. Without the strictness annotation, a pointer on the heap would be passed to them (i.e. a pointer on the register would point to the Position structure which would have a pointer to the integer, not very nice). HTH, PS: I'm not sure if the unboxed operations I wrote are correct, but you get the idea :). -- Felipe. From daniel.is.fischer at web.de Thu Feb 26 06:33:01 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Feb 26 06:22:00 2009 Subject: [Haskell-beginners] Meaning of '!' in record defintion? UNPACK? In-Reply-To: References: <20090226214240.2c774606.mle+cl@mega-nerd.com> <9540020A-ECB1-4A6D-8808-E25F227F9B6D@gmail.com> Message-ID: <200902261233.01723.daniel.is.fischer@web.de> Am Donnerstag, 26. Februar 2009 12:07 schrieb Colin Paul Adams: > >>>>> "Thomas" == Thomas Davie writes: > > Thomas> The {-# UNPACK #-} tells the compiler that it can unpack > Thomas> the Int ? meaning that a Position will be neatly packed > Thomas> into 12 bytes. > > What would be the difference if there was no UNPACK pragma? Section 8.12.10 of the users' guide says: "The UNPACK indicates to the compiler that it should unpack the contents of a constructor field into the constructor itself, removing a level of indirection." It has more, and also says when it's not a good idea to use it. Int is defined as data Int = I# Int# where Int# is a raw machine int. If you use the {-# UNPACK #-} pragma, you tell GHC that you'd very much like Position to be stored as constructor + three contiguous raw machine integers. Mostly, it will do so. If you don't use the pragma, i.e. have data Position = Position { posOffset :: !Int , posRow :: !Int , posColumn :: !Int } , GHC may or may not decide to store it thus, with -O2 it's not too unlikely, I think. But it's also not unlikely that it will be stored as constructor + three pointers to three evaluated Ints, which is much better than pointers to thunks, but not as good as having the raw values directly by the constructor. Cheers, Daniel From magnus at therning.org Thu Feb 26 06:36:29 2009 From: magnus at therning.org (Magnus Therning) Date: Thu Feb 26 06:25:40 2009 Subject: [Haskell-beginners] Meaning of '!' in record defintion? UNPACK? In-Reply-To: <200902261233.01723.daniel.is.fischer@web.de> References: <20090226214240.2c774606.mle+cl@mega-nerd.com> <9540020A-ECB1-4A6D-8808-E25F227F9B6D@gmail.com> <200902261233.01723.daniel.is.fischer@web.de> Message-ID: On Thu, Feb 26, 2009 at 11:33 AM, Daniel Fischer wrote: > Am Donnerstag, 26. Februar 2009 12:07 schrieb Colin Paul Adams: >> >>>>> "Thomas" == Thomas Davie writes: >> >> ? ? Thomas> The {-# UNPACK #-} tells the compiler that it can unpack >> ? ? Thomas> the Int ? meaning that a Position will be neatly packed >> ? ? Thomas> into 12 bytes. >> >> What would be the difference if there was no UNPACK pragma? > > Section 8.12.10 of the users' guide says: > "The UNPACK indicates to the compiler that it should unpack the contents of a > constructor field into the constructor itself, removing a level of > indirection." > > It has more, and also says when it's not a good idea to use it. > > Int is defined as > > data Int = I# Int# > > where Int# is a raw machine int. If you use the {-# UNPACK #-} pragma, you > tell GHC that you'd very much like Position to be stored as constructor + > three contiguous raw machine integers. Mostly, it will do so. > If you don't use the pragma, i.e. have > > ? ?data Position = > ? ? ? ? ? Position { posOffset :: !Int > ? ? ? ? ? ? ? ? ? ?, posRow :: !Int > ? ? ? ? ? ? ? ? ? ?, posColumn :: !Int > ? ? ? ? ? ? ? ? ? ?} > > , GHC may or may not decide to store it thus, with -O2 it's not too unlikely, > I think. But it's also not unlikely that it will be stored as constructor + > three pointers to three evaluated Ints, which is much better than pointers to > thunks, but not as good as having the raw values directly by the constructor. > > Cheers, > Daniel > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > Are there any guarantees here, or is it just me telling the compiler to please do what I say, but the compiler can decide not to follow my wishes? Is address aligning predictable? I'm basically wondering if it'd be possible to to use this mechanism to avoid using FFI when reading data that basically is a dump of structs in a C program. /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus?therning?org Jabber: magnus?therning?org http://therning.org/magnus identi.ca|twitter: magthe From daniel.is.fischer at web.de Thu Feb 26 06:45:30 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Feb 26 06:34:29 2009 Subject: [Haskell-beginners] Defeating type inference In-Reply-To: <49A67C5F.40507@foo.me.uk> References: <49A5DFC7.10507@foo.me.uk> <200902261109.44223.daniel.is.fischer@web.de> <49A67C5F.40507@foo.me.uk> Message-ID: <200902261245.30663.daniel.is.fischer@web.de> Am Donnerstag, 26. Februar 2009 12:26 schrieb Philip Scott: > Hi ho, > > > One more improvement, include also Enum among the derived classes, then > > you can write > > > > months = cycle [Jan .. Dec] > > > > Oh, and cycle is also exported from the Prelude, so it's not necessary to > > import Data.List for that (though you will probably want to imoprt it > > anyway). > > Ohh so many little tasty titbits of Haskell - I was trying for ages to > get the '..' operator to work. I guess I will start to know where to > look for these guys as time goes on. The '..' things are syntactic sugar for enumerations: [a .. ] === enumFrom a [a, b .. ] === enumFromThen a b [a .. b] === enumFromTo a b [a, b .. c] === enumFromThenTom a b c they are methods of class Enum. :i Enum in ghci or hugs gives the class information (methods and instances currently in scope). One place to look for such things is the Haskell report, also many tutorials and books have a sectioned 'Overview of standard type classes' or some such, there you should find this and similarly important things. Another method is to ask ghci or hugs - you have to do it the right way, which is not always obvious - as in Prelude> :t \a b -> [a .. b] \a b -> [a .. b] :: (Enum t) => t -> t -> [t] so you know you have to look at Enum Prelude> :i Enum class Enum a where succ :: a -> a pred :: a -> a toEnum :: Int -> a fromEnum :: a -> Int enumFrom :: a -> [a] enumFromThen :: a -> a -> [a] enumFromTo :: a -> a -> [a] enumFromThenTo :: a -> a -> a -> [a] -- Defined in GHC.Enum instance Enum Integer -- Defined in GHC.Num instance Enum Float -- Defined in GHC.Float instance Enum Double -- Defined in GHC.Float instance Enum Bool -- Defined in GHC.Enum instance Enum Ordering -- Defined in GHC.Enum instance Enum Char -- Defined in GHC.Enum instance Enum () -- Defined in GHC.Enum instance Enum Int -- Defined in GHC.Enum looking at this, you don't see '..', but you see two functions with the correct type, that it's more likely to be enumFromTo rather than enumFromThen can easily be inferred from the functions' names. > > Cheers, > > Philip Cheers, Daniel From daniel.is.fischer at web.de Thu Feb 26 06:55:56 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Feb 26 06:45:01 2009 Subject: [Haskell-beginners] Meaning of '!' in record defintion? UNPACK? In-Reply-To: References: <20090226214240.2c774606.mle+cl@mega-nerd.com> <200902261233.01723.daniel.is.fischer@web.de> Message-ID: <200902261255.56251.daniel.is.fischer@web.de> Am Donnerstag, 26. Februar 2009 12:36 schrieb Magnus Therning: > Are there any guarantees here, or is it just me telling the compiler > to please do what I say, but the compiler can decide not to follow my > wishes? I don't think there are guarantees, as the section ends with: "If a field cannot be unpacked, you will not get a warning, so it might be an idea to check the generated code with -ddump-simpl. See also the -funbox-strict-fields flag, which essentially has the effect of adding {-# UNPACK #-} to every strict constructor field." But it should be very likely to do what you want (of course, always compile with -O or -O2). > Is address aligning predictable? Absolutely no idea, sorry. > > I'm basically wondering if it'd be possible to to use this mechanism > to avoid using FFI when reading data that basically is a dump of > structs in a C program. I doubt it, as I understand it, with {-# UNPACK #-}, you'll have the layout constuctor rawdata and the C structs won't have the constructor. > > /M Cheers, Daniel From bieffe62 at gmail.com Thu Feb 26 14:58:02 2009 From: bieffe62 at gmail.com (Francesco Bochicchio) Date: Thu Feb 26 14:46:58 2009 Subject: [Haskell-beginners] Array and IArray Message-ID: Hello all, I'm reading stuff about the different types of arrays in Haskell ... One of the things that I don't understand If I do: import Data.Array arr = listArray (1,10) [1..] the type of arr is Array. My question is: is this array an instance of the type class defined in Data.Array.IArray? Or there is another kind of immutable boxed array somewhere in haskell libraries? The documentation makes a reference to 'the Array type exported by Data.Array.IArray' but if I do: import Data.Array.IArray arr = listArray (1,10) [1..] I get a couple of compiler errors Ciao & thanks in advance ----- FB -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090226/d5c28007/attachment.htm From RafaelGCPP.Linux at gmail.com Thu Feb 26 15:59:39 2009 From: RafaelGCPP.Linux at gmail.com (Rafael Gustavo da Cunha Pereira Pinto) Date: Thu Feb 26 15:48:38 2009 Subject: [Haskell-beginners] Array and IArray In-Reply-To: References: Message-ID: <351ff25e0902261259n331fb565n30ea20f3d8136082@mail.gmail.com> Please, post the error messages. Maybe all is needed is an explicit type declaration... On Thu, Feb 26, 2009 at 16:58, Francesco Bochicchio wrote: > Hello all, > > I'm reading stuff about the different types of arrays in Haskell ... > > One of the things that I don't understand > If I do: > > import Data.Array > arr = listArray (1,10) [1..] > > the type of arr is Array. My question is: is this array an instance of the > type class defined in Data.Array.IArray? > Or there is another kind of immutable boxed array somewhere in haskell > libraries? > The documentation makes a reference to 'the Array type exported by > Data.Array.IArray' but if I do: > > import Data.Array.IArray > arr = listArray (1,10) [1..] > > I get a couple of compiler errors > > Ciao & thanks in advance > ----- > FB > > > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -- Rafael Gustavo da Cunha Pereira Pinto Electronic Engineer, MSc. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090226/a80d9267/attachment.htm From daniel.is.fischer at web.de Thu Feb 26 16:17:31 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Feb 26 16:06:28 2009 Subject: [Haskell-beginners] Array and IArray In-Reply-To: References: Message-ID: <200902262217.31594.daniel.is.fischer@web.de> Am Donnerstag, 26. Februar 2009 20:58 schrieb Francesco Bochicchio: > Hello all, > > I'm reading stuff about the different types of arrays in Haskell ... > > One of the things that I don't understand > If I do: > > import Data.Array > arr = listArray (1,10) [1..] > > the type of arr is Array. My question is: is this array an instance of the > type class defined in Data.Array.IArray? Yes, it is. > Or there is another kind of immutable boxed array somewhere in haskell > libraries? There are many array libraries, I wouldn't be surprised if one of them also contained an immutable boxed array type. > The documentation makes a reference to 'the Array type exported by > Data.Array.IArray' but if I do: > > import Data.Array.IArray > arr = listArray (1,10) [1..] > > I get a couple of compiler errors like: Ambiguous type variables `t', `a' in the constraint: `IArray a t' arising from a use of `listArray' at ArrayI.hs:5:6-27 Possible cause: the monomorphism restriction applied to the following: arr :: a Integer t (bound at ArrayI.hs:5:0) Probable fix: give these definition(s) an explicit type signature or use -fno-monomorphism-restriction Ambiguous type variable `t' in the constraints: `Enum t' arising from the arithmetic sequence `1 .. ' at ArrayI.hs:5:23-27 `Num t' arising from the literal `1' at ArrayI.hs:5:24 Possible cause: the monomorphism restriction applied to the following: arr :: a Integer t (bound at ArrayI.hs:5:0) Probable fix: give these definition(s) an explicit type signature or use -fno-monomorphism-restriction Note that ghci gives two probable fixes, both work. The point is that Data.Array.IArray also exports the typeclass IArray. If you import Data.Array, the type of listArray is listArray :: (Ix i) => (i, i) -> [e] -> Array i e So arr :: (Ix i, Num i, Num e, Enum e) => Array i e (the index type must belong to Num because of the literals 1 and 10 for the array bounds, the element type must belong to Num because of the literal 1 and to Enum because of the use of enumFrom - [1 .. ]) Now defaulting (section 4.3.4 of the Haskell report) is used to determine a monomorphic type for arr. arr must have a monomorphic type because it is defined by a simple pattern binding (just a variable name on the left of '=') and we have the monomorphism restriction (section 4.5.5 of the Haskell report, see also http://www.haskell.org/haskellwiki/Monomorphism_restriction) Both i and e default to Integer, giving arr :: Array Integer Integer Disabling the monomorphism restriction, arr retains its polymorphic type *ArrayI> :t arr arr :: (Num t, Num t1, Enum t1, Ix t) => Array t t1 Now if you import Data.Array.IArray, listArray has a more general type: listArray :: (Ix i, IArray a e) => (i, i) -> [e] -> a i e Then type inference determines the type of arr as *ArrayI> :t arr arr :: (Num t, Num t1, Enum t1, IArray a t1, Ix t) => a t t1 But, arr is still defined by a simple pattern binding, so the monomorphism restriction kicks in again, and GHC tries to give arr a monomorphic type, fixing a, t and t1 Alas, says the report in section 4.3.4: an ambiguous type variable, v, is defaultable if: * v appears only in constraints of the form C v, where C is a class, and * at least one of these classes is a numeric class, (that is, Num or a subclass of Num), and * all of these classes are defined in the Prelude or a standard library - all classes defined in the Prelude or standard library? Yes - at least one of these classes is a numeric class? Not for a! - I'm not quite sure, but the fact that IArray is a multiparameter type class may also hinder defaulting. So a monomorphic type for arr could not be determined, hence the errors. If you give an explicit type signature or disable the monomorphism restriction, al goes well whether you import Data.Array or Data.Array.IArray. > > Ciao & thanks in advance > ----- > FB HTH, Daniel From RafaelGCPP.Linux at gmail.com Thu Feb 26 16:55:31 2009 From: RafaelGCPP.Linux at gmail.com (Rafael Gustavo da Cunha Pereira Pinto) Date: Thu Feb 26 16:44:27 2009 Subject: Fwd: [Haskell-beginners] Array and IArray In-Reply-To: <351ff25e0902261354i16028979t61ea69e7eff3d067@mail.gmail.com> References: <351ff25e0902261259n331fb565n30ea20f3d8136082@mail.gmail.com> <200902262219.17179.daniel.is.fischer@web.de> <351ff25e0902261354i16028979t61ea69e7eff3d067@mail.gmail.com> Message-ID: <351ff25e0902261355n28305183pc0df36287b321ef3@mail.gmail.com> IArray define TONS of instances of IArray class... You will surely have to define a type for your expression. For your example you could use: arr::Array Int Int On Thu, Feb 26, 2009 at 18:19, Daniel Fischer wrote: > Am Donnerstag, 26. Februar 2009 21:59 schrieb Rafael Gustavo da Cunha > Pereira > Pinto: > > Please, post the error messages. > > > > Maybe all is needed is an explicit type declaration... > > Yup! > Are you an experienced victim of the monomorphism restriction? > > Cheers, > Daniel > > -- Rafael Gustavo da Cunha Pereira Pinto Electronic Engineer, MSc. -- Rafael Gustavo da Cunha Pereira Pinto Electronic Engineer, MSc. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090226/ffcb5926/attachment-0001.htm From haskell-beginners at foo.me.uk Thu Feb 26 17:07:25 2009 From: haskell-beginners at foo.me.uk (Philip Scott) Date: Thu Feb 26 16:56:27 2009 Subject: [Haskell-beginners] Lambda Functions Message-ID: <49A7129D.10300@foo.me.uk> Okay, thanks everyone for the help with the last question; I've got another one for you if you are keen. It's short and sweet. You can easily define a lambda expression that takes a tuple - e.g. in ghci > let foo = \(x,y) -> 42 foo :: (t, t1) -> Integer > foo (5,5) 42 Yay. Now that isn't a very exciting function. Tt takes two anythings and gives you a nice meaningful number. Now let us say for some perverse reason I want to make a lambda to test for equality. That is, reimplement the functionality of (==) using, well, (==). > let foo2 = \(x,y) -> x == y foo2 :: ((), ()) -> Bool Uh-oh. Now things are getting a little odd. I am not entirely sure what that type signature means (I was expecting to see something about the types having to be the same and an instance of the Eq class but alas..) The function certainly doesn't do what I want it to: > foo2 (5,5) No instance for (Num ()) arising from the literal `5' at :1:6 Possible fix: add an instance declaration for (Num ()) In the expression: 5 In the first argument of `foo2', namely `(5, 5)' In the expression: foo2 (5, 5) This is itself a stupid problem, but it is a distilled version of some trouble I was having writing a filter that works on a list of tuples. Any pointers or slaps in the face for being too stupid warmly welcomed. I have already tried my usual trick of smothering the thing parentheses but it appeared to be all in vain. All the best, Philip From tom.davie at gmail.com Thu Feb 26 17:25:42 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Feb 26 17:14:46 2009 Subject: [Haskell-beginners] Lambda Functions In-Reply-To: <49A7129D.10300@foo.me.uk> References: <49A7129D.10300@foo.me.uk> Message-ID: On 26 Feb 2009, at 23:07, Philip Scott wrote: > Okay, thanks everyone for the help with the last question; I've got > another one for you if you are keen. It's short and sweet. > > You can easily define a lambda expression that takes a tuple - e.g. > in ghci > > > let foo = \(x,y) -> 42 > foo :: (t, t1) -> Integer > > > foo (5,5) > 42 > > Yay. Now that isn't a very exciting function. Tt takes two anythings > and gives you a nice meaningful number. Now let us say for some > perverse reason I want to make a lambda to test for equality. That > is, reimplement the functionality of (==) using, well, (==). > > > let foo2 = \(x,y) -> x == y > > foo2 :: ((), ()) -> Bool > > Uh-oh. Now things are getting a little odd. I am not entirely sure > what that type signature means (I was expecting to see something > about the types having to be the same and an instance of the Eq > class but alas..) The function certainly doesn't do what I want it to: > > > foo2 (5,5) > > No instance for (Num ()) > arising from the literal `5' at :1:6 > Possible fix: add an instance declaration for (Num ()) > In the expression: 5 > In the first argument of `foo2', namely `(5, 5)' > In the expression: foo2 (5, 5) > > This is itself a stupid problem, but it is a distilled version of > some trouble I was having writing a filter that works on a list of > tuples. Any pointers or slaps in the face for being too stupid > warmly welcomed. I have already tried my usual trick of smothering > the thing parentheses but it appeared to be all in vain. I'm not 100% certain here, so someone may correct me, but I think this is what's going on: foo2 has no arguments. Because of this, ghci makes it a CAF. At this point, the monomorphism restriction kicks in, and the CAF has to be monomorphic. ghc then chooses a type for it, and defaulting choses the most simple type it can find ? () (this is the type that contains one value ? () ). If instead, you do let foo3 (x,y) = x == y, you will get the type you expected. Another way to write it ofc would simply be uncurry (==). Bob From felipe.lessa at gmail.com Thu Feb 26 17:51:32 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Thu Feb 26 17:40:27 2009 Subject: [Haskell-beginners] Lambda Functions In-Reply-To: References: <49A7129D.10300@foo.me.uk> Message-ID: On Thu, Feb 26, 2009 at 7:25 PM, Thomas Davie wrote: > I'm not 100% certain here, so someone may correct me, but I think this is > what's going on: [snip] Yep, that's right. Is it just me or the monomorphism restriction suddenly became the hot topic here on beginners? > Another way to write it ofc would simply be uncurry (==). Better yet, write a type signature. I highly recommend writing type signatures for *all* top-level definitions, including non-exported ones: - You avoid most cases where the monomorphism restriction would bother you. - You avoid type errors on other functions (sometimes you make a mistake but the code type checks with a wrong signature, and the type error shows up only when you use the function elsewhere). - It gives you some insights before implementing, and helps whoever reads your code. - It allows you to specialize the code when polymorphism is not needed. Probably there are other reasons as well, but these are the most prominent. -- Felipe. From byorgey at seas.upenn.edu Thu Feb 26 17:59:36 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Thu Feb 26 17:48:30 2009 Subject: [Haskell-beginners] Lambda Functions In-Reply-To: References: <49A7129D.10300@foo.me.uk> Message-ID: <20090226225936.GA31988@seas.upenn.edu> On Thu, Feb 26, 2009 at 07:51:32PM -0300, Felipe Lessa wrote: > > Better yet, write a type signature. I highly recommend writing type > signatures for *all* top-level definitions, including non-exported > ones: > > - It gives you some insights before implementing Hear, hear! If you can't write down the intended type of a function, you have very little hope of implementing it correctly. =) -Brent From wagner.andrew at gmail.com Thu Feb 26 18:01:31 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Thu Feb 26 17:50:31 2009 Subject: [Haskell-beginners] Lambda Functions In-Reply-To: References: <49A7129D.10300@foo.me.uk> Message-ID: Excellent list. It seems like every time I hear about a problem with the MMR, I go "wow, how come I never ran across that? oh yeah, because I write type signatures..." On Thu, Feb 26, 2009 at 5:51 PM, Felipe Lessa wrote: > On Thu, Feb 26, 2009 at 7:25 PM, Thomas Davie wrote: > > I'm not 100% certain here, so someone may correct me, but I think this is > > what's going on: > [snip] > > Yep, that's right. Is it just me or the monomorphism restriction > suddenly became the hot topic here on beginners? > > > Another way to write it ofc would simply be uncurry (==). > > Better yet, write a type signature. I highly recommend writing type > signatures for *all* top-level definitions, including non-exported > ones: > > - You avoid most cases where the monomorphism restriction would bother you. > > - You avoid type errors on other functions (sometimes you make a > mistake but the code type checks with a wrong signature, and the type > error shows up only when you use the function elsewhere). > > - It gives you some insights before implementing, and helps whoever > reads your code. > > - It allows you to specialize the code when polymorphism is not needed. > > Probably there are other reasons as well, but these are the most prominent. > > -- > Felipe. > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090226/8c993f12/attachment.htm From korgulec at gmail.com Thu Feb 26 19:06:37 2009 From: korgulec at gmail.com (frea) Date: Thu Feb 26 18:55:40 2009 Subject: [Haskell-beginners] using parametrized monads and Prelude.>> Message-ID: Hello, I would like to create few functions which use parametrized monads (defined as in http://computationalthoughts.blogspot.com/2009/02/comment-on-parameterized-monads.html ) and export their functionality outside a module and use them in a do statement. For example three exported funtions : func1 num = do x <- get put (show (x + num)) func2 num = do x <- get put (((read x)::Int) + num) execWith0 actions = runState actions 0 And in an another module, which has Prelude imported : k = execWith0 ( do func1 10 func2 5) Unfortunately this doesn't compile as in the second module >> is different than in PMonad. Is there any way which I could make it work? Michal From patrick.leboutillier at gmail.com Thu Feb 26 20:46:32 2009 From: patrick.leboutillier at gmail.com (Patrick LeBoutillier) Date: Thu Feb 26 20:35:26 2009 Subject: [Haskell-beginners] Overriding >>= for a Monad? Message-ID: Hi all, I'm using Control.Monad.StateT as such: data TapState = TapState { planSet :: Bool, noPlan :: Bool, skipAll :: Bool, testDied :: Bool, expectedTests :: Int, executedTests :: Int, failedTests :: Int } deriving (Show) type TAP a = StateT TapState IO a but I'd like to provide my own >>= function. Is there a way to "derive" a new type from StateT in order to implement my own >>=? Is thin done using "instance"? Thanks, Patrick -- ===================== Patrick LeBoutillier Rosem?re, Qu?bec, Canada From alexander.dunlap at gmail.com Thu Feb 26 21:24:15 2009 From: alexander.dunlap at gmail.com (Alexander Dunlap) Date: Thu Feb 26 21:13:11 2009 Subject: [Haskell-beginners] Overriding >>= for a Monad? In-Reply-To: References: Message-ID: <57526e770902261824w347e05bap8ee26de4952f13db@mail.gmail.com> On Thu, Feb 26, 2009 at 5:46 PM, Patrick LeBoutillier wrote: > Hi all, > > I'm using Control.Monad.StateT as such: > > ?data TapState = TapState { > ? planSet :: Bool, > ? noPlan :: Bool, > ? skipAll :: Bool, > ? testDied :: Bool, > ? expectedTests :: Int, > ? executedTests :: Int, > ? failedTests :: Int > ?} deriving (Show) > > ?type TAP a = StateT TapState IO a > > but I'd like to provide my own >>= function. Is there a way to > "derive" a new type from StateT in order to implement my own >>=? > Is thin done using "instance"? > > Thanks, > > Patrick > > -- > ===================== > Patrick LeBoutillier > Rosem?re, Qu?bec, Canada The most direct way would probably to copy StateT's source code and tinker with the >>= definition (also change the name to MyStateT or whatever). You could also define > newtype MyStateT s a = MyStateT (StateT s IO a) > > instance Monad (MyStateT s) where > return = MyStateT . return > (>>=) = ... Alex From tom.davie at gmail.com Fri Feb 27 03:01:39 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Fri Feb 27 02:50:49 2009 Subject: [Haskell-beginners] using parametrized monads and Prelude.>> In-Reply-To: References: Message-ID: On 27 Feb 2009, at 01:06, frea wrote: > Hello, > I would like to create few functions which use parametrized monads > (defined as in http://computationalthoughts.blogspot.com/2009/02/comment-on-parameterized-monads.html > ) and export their functionality outside a module and use them in a do > statement. > For example three exported funtions : > > func1 num = do > x <- get > put (show (x + num)) > > func2 num = do > x <- get > put (((read x)::Int) + num) > > execWith0 actions = runState actions 0 > > And in an another module, which has Prelude imported : > > k = execWith0 ( do > func1 10 > func2 5) > > Unfortunately this doesn't compile as in the second module >> is > different than in PMonad. Is there any way which I could make it work? The definition of (>>) is not determined by which module you're in, instead by what the types it is operating on are. Check which monad these functions really are in, and you'll probably find your error. Bob From pscott at foo.me.uk Thu Feb 26 06:21:31 2009 From: pscott at foo.me.uk (Philip Scott) Date: Fri Feb 27 03:00:20 2009 Subject: [Haskell-beginners] Defeating type inference In-Reply-To: <57526e770902252105r5412814dx1f6130453f58fe07@mail.gmail.com> References: <49A5DFC7.10507@foo.me.uk> <57526e770902252105r5412814dx1f6130453f58fe07@mail.gmail.com> Message-ID: <49A67B3B.5000800@foo.me.uk> Hi Alex, > The problem is that when you go fro >> months = range (Jan,Dec) : months >> realmonths = concat months >> > to >> months = concat (range (Jan,Dec) : months) >> > you're not just collapsing the two functions, you're changing the > definition (and type!) of "months" which you referred to within the > months function. Since months is a recursive function, you can't > necessary fold in the definition of realmonths because you want the > recursion to apply to the original months, not the original > realmonths. > > Of course, why didn't I see that :) I think I had managed to get my head into its own recursive loop.. I think I might have to replace my evening glass or three of wine with some Red Bull while I am getting my mind around this stuff. > As you suspected, there are better and simpler ways of doing this > available, although your way is good for getting the hang of > recursion, even though experienced haskellers really don't use > recursion all that much. (Most prefer to use functions that > encapsulate recursion *patterns* such as map, filter, folds and many > more.) > Thank you very much for you help and suggestions, I shall bear them in mind. - Philip From pscott at foo.me.uk Thu Feb 26 06:26:23 2009 From: pscott at foo.me.uk (Philip Scott) Date: Fri Feb 27 03:00:34 2009 Subject: [Haskell-beginners] Defeating type inference In-Reply-To: <200902261109.44223.daniel.is.fischer@web.de> References: <49A5DFC7.10507@foo.me.uk> <57526e770902252105r5412814dx1f6130453f58fe07@mail.gmail.com> <200902261109.44223.daniel.is.fischer@web.de> Message-ID: <49A67C5F.40507@foo.me.uk> Hi ho, > One more improvement, include also Enum among the derived classes, then you > can write > > months = cycle [Jan .. Dec] > > Oh, and cycle is also exported from the Prelude, so it's not necessary to > import Data.List for that (though you will probably want to imoprt it > anyway). > Ohh so many little tasty titbits of Haskell - I was trying for ages to get the '..' operator to work. I guess I will start to know where to look for these guys as time goes on. Cheers, Philip From mattrussell324 at googlemail.com Fri Feb 27 03:41:36 2009 From: mattrussell324 at googlemail.com (Matt R) Date: Fri Feb 27 03:30:29 2009 Subject: [Haskell-beginners] Lambda Functions In-Reply-To: References: <49A7129D.10300@foo.me.uk> Message-ID: <2f9e00bc0902270041s31203f2al98239a2dc4a8494c@mail.gmail.com> On 26/02/2009, Andrew Wagner wrote: > Excellent list. It seems like every time I hear about a problem with the > MMR, I go "wow, how come I never ran across that? oh yeah, because I write > type signatures..." Certainly. Still, it seems relatively easy to bump into it when tinkering on ghci. Out of interest, what are the disadvantages to blanket turning off the restriction? -- Matt From colin at colina.demon.co.uk Fri Feb 27 11:36:09 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Fri Feb 27 11:25:05 2009 Subject: [Haskell-beginners] Module structure Message-ID: If I want to write part of the code for my program as a library, and so put those modules into a hierarchical module structure (with the non-library code in no module), do I have to structure the directories in a special way to get the module search to work? -- Colin Adams Preston Lancashire From chaddai.fouche at gmail.com Fri Feb 27 12:26:51 2009 From: chaddai.fouche at gmail.com (=?UTF-8?B?Q2hhZGRhw68gRm91Y2jDqQ==?=) Date: Fri Feb 27 12:15:43 2009 Subject: [Haskell-beginners] Module structure In-Reply-To: References: Message-ID: On Fri, Feb 27, 2009 at 5:36 PM, Colin Paul Adams wrote: > If I want to write part of the code for my program as a library, and > so put those modules into a hierarchical module structure (with the > non-library code in no module), do I have to structure the directories > in a special way to get the module search to work? Yes, module My.Pretty.Little.Module must be in file "My/Pretty/Little/Module.hs" in one of the root directories (which can be specified on the command line to ghc, or in the .cabal file if you use an unusual directory structure). Note that this only apply before compiling, the executable is independent. -- Jeda? From byorgey at seas.upenn.edu Fri Feb 27 12:31:22 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Fri Feb 27 12:20:13 2009 Subject: [Haskell-beginners] Lambda Functions In-Reply-To: <2f9e00bc0902270041s31203f2al98239a2dc4a8494c@mail.gmail.com> References: <49A7129D.10300@foo.me.uk> <2f9e00bc0902270041s31203f2al98239a2dc4a8494c@mail.gmail.com> Message-ID: <20090227173122.GA31210@seas.upenn.edu> The only disadvantage is that some things you might expect to be constants will actually get recomputed every time they are used. For example, suppose you define foo = very expensive computation involving a bunch of numbers You might think that foo will get computed just once, the first time it is needed. However, if foo ends up with a polymorphic type, like, say foo :: Num a => a then it is not actually a constant, but a function which takes a Num dictionary (i.e. a record of the Num methods) as an argument. So it will be recomputed every time it is used, since it might have different values for different types. Now, you might wonder why this is such a big deal. The answer is: it isn't. I have the MR automatically turned off in my .ghci file, and I've never missed it. Furthermore, the monomorphism restriction will be removed in the next version of the Haskell language standard. -Brent On Fri, Feb 27, 2009 at 08:41:36AM +0000, Matt R wrote: > On 26/02/2009, Andrew Wagner wrote: > > Excellent list. It seems like every time I hear about a problem with the > > MMR, I go "wow, how come I never ran across that? oh yeah, because I write > > type signatures..." > > Certainly. Still, it seems relatively easy to bump into it when > tinkering on ghci. > > Out of interest, what are the disadvantages to blanket turning off the > restriction? > > -- Matt > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners From colin at colina.demon.co.uk Fri Feb 27 12:39:26 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Fri Feb 27 12:28:20 2009 Subject: [Haskell-beginners] Module structure In-Reply-To: (=?iso-8859-1?Q?=22Chadda=EF_Fouch=E9=22's?= message of "Fri\, 27 Feb 2009 18\:26\:51 +0100") References: Message-ID: >>>>> "Chadda?" == Chadda? Fouch? writes: Chadda?> On Fri, Feb 27, 2009 at 5:36 PM, Colin Paul Adams Chadda?> wrote: >> If I want to write part of the code for my program as a >> library, and so put those modules into a hierarchical module >> structure (with the non-library code in no module), do I have >> to structure the directories in a special way to get the module >> search to work? Chadda?> Yes, module My.Pretty.Little.Module must be in file Chadda?> "My/Pretty/Little/Module.hs" in one of the root Chadda?> directories (which can be specified on the command line Chadda?> to ghc, or in the .cabal file if you use an unusual Chadda?> directory structure). Note that this only apply before Chadda?> compiling, the executable is independent. Thank you. Where do I find out what the root directories are? Is mt project directory one of them? -- Colin Adams Preston Lancashire From dpfrey at shaw.ca Fri Feb 27 13:55:50 2009 From: dpfrey at shaw.ca (David Frey) Date: Fri Feb 27 13:44:49 2009 Subject: [Haskell-beginners] Module structure In-Reply-To: References: Message-ID: <617ad6e73214998fc481904b1cdbddcc@localhost> On Fri, 27 Feb 2009 18:26:51 +0100, Chadda? Fouch? wrote: > On Fri, Feb 27, 2009 at 5:36 PM, Colin Paul Adams > wrote: >> If I want to write part of the code for my program as a library, and >> so put those modules into a hierarchical module structure (with the >> non-library code in no module), do I have to structure the directories >> in a special way to get the module search to work? > > Yes, module My.Pretty.Little.Module must be in file > "My/Pretty/Little/Module.hs" in one of the root directories (which can > be specified on the command line to ghc, or in the .cabal file if you > use an unusual directory structure). > Note that this only apply before compiling, the executable is independent. This last line sounds a bit fishy to me. I think what would happen here is that you would create a separate module, but when your application is linked, any code that is used from that module would be compiled and included into your binary. I suspect that what Colin may have been looking for are instructions on how to create a standalone library that his application can dynamically link to. I'm curious about this as well. From colin at colina.demon.co.uk Fri Feb 27 14:04:25 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Fri Feb 27 13:53:20 2009 Subject: [Haskell-beginners] Module structure In-Reply-To: <617ad6e73214998fc481904b1cdbddcc@localhost> (David Frey's message of "Fri\, 27 Feb 2009 10\:55\:50 -0800") References: <617ad6e73214998fc481904b1cdbddcc@localhost> Message-ID: >>>>> "David" == David Frey writes: David> I suspect that what Colin may have been David> looking for are instructions on how to create a standalone David> library that his application can dynamically link to. I'm David> curious about this as well. No, I was only interested in how to structure the library on disk. -- Colin Adams Preston Lancashire From will_n48 at yahoo.com Fri Feb 27 17:59:05 2009 From: will_n48 at yahoo.com (Will Ness) Date: Fri Feb 27 17:53:53 2009 Subject: [Haskell-beginners] Re: Defeating type inference References: <49A5DFC7.10507@foo.me.uk> <57526e770902252105r5412814dx1f6130453f58fe07@mail.gmail.com> <49A67B3B.5000800@foo.me.uk> Message-ID: Philip Scott foo.me.uk> writes: > > Hi Alex, > > The problem is that when you go fro > >> months = range (Jan,Dec) : months > >> realmonths = concat months > >> Another way to go about this is to always look at types. You've correctly surmised that you have to refer back to the name you're defining, months, in a recusive definition, so let's write it down as months = range (Jan,Dec) `somehowJoinWith` months What is somehowJoinWith's type? Its first argument is [Month], let's call it [a]. So somehowJoinWith :: [a] -> b -> b But you want its result to be a list of Month's too. So b = [a] and somehowJoinWith :: [a] -> [a] -> [a] Cons (:) simply won't fit here, as it is :: a -> [a] -> [a]. (++) OTOH does fit, and is exactly what you need. Thinking with types helps clarify the problem always. It helps us not to confuse oranges and boxes-of-oranges. :) Cheers, From bugfact at gmail.com Fri Feb 27 18:40:57 2009 From: bugfact at gmail.com (Peter Verswyvelen) Date: Fri Feb 27 18:29:47 2009 Subject: [Haskell-beginners] Lambda Functions In-Reply-To: <20090227173122.GA31210@seas.upenn.edu> References: <49A7129D.10300@foo.me.uk> <2f9e00bc0902270041s31203f2al98239a2dc4a8494c@mail.gmail.com> <20090227173122.GA31210@seas.upenn.edu> Message-ID: On Fri, Feb 27, 2009 at 6:31 PM, Brent Yorgey wrote: > The only disadvantage is that some things you might expect to be > constants will actually get recomputed every time they are used. For > example, suppose you define > > foo = very expensive computation involving a bunch of numbers > > You might think that foo will get computed just once, the first time > it is needed. However, if foo ends up with a polymorphic type, like, > say > > foo :: Num a => a > > then it is not actually a constant, but a function which takes a Num > dictionary (i.e. a record of the Num methods) as an argument. So it > will be recomputed every time it is used, since it might have > different values for different types. Yes indeed. Beginners might want to verify this with the following little program (just assume 42 takes a very long to compute, on some alien computer this took 7? million years ;-) import Debug.Trace foo :: Num a => a foo = trace "foo" $ 42 bar :: Int bar = trace "bar" $ 42 When evaluating foo (e.g in GHCi) "foo" will be printed every time, bar only once. I guess a clever implementation would only compute foo once for each different type of a? But then of course you'll hit a runtime performance penalty every time when accessing foo since this will require a lookup... Mmm, this feels as a case where you can't determine at compile time if a function - in this case a polymorphic CAF - will need memoization or not... For example (just a quick hack) import Data.Typeable import Data.IORef import qualified Data.IntMap as M import System.IO.Unsafe import Debug.Trace fooCache :: IORef (M.IntMap a) fooCache = unsafePerformIO $ newIORef M.empty foo :: (Typeable a, Num a) => a foo = unsafePerformIO $ do key <- typeRepKey (typeOf value) atomicModifyIORef fooCache (updateCache key) where value = trace "foo is computed" $ 42 updateCache key cache = case key `M.lookup` cache of Just n -> (cache, trace "foo is cached" n) Nothing -> (M.insert key value cache, value) Now, you might wonder why this is such a big deal. The answer is: it > isn't. I have the MR automatically turned off in my .ghci file, and > I've never missed it. Furthermore, the monomorphism restriction will > be removed in the next version of the Haskell language standard. Cool. But I guess the next version of the standard will take a while? :) -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090228/91955b29/attachment.htm From codetojoy at gmail.com Fri Feb 27 21:50:21 2009 From: codetojoy at gmail.com (Michael Easter) Date: Fri Feb 27 21:39:11 2009 Subject: [Haskell-beginners] clarification on IO Message-ID: <1d393c9d0902271850i4b970c9dg43676ad34c77ff5f@mail.gmail.com> Folks, I've been reading RWH and this http://www.haskell.org/haskellwiki/IO_inside#Haskell_is_a_pure_language I think I understand monads. I think I understand how IO is much different from, e.g. Maybe, State, etc. However there are some turns of phrase with respect to IO that have me baffled. I am giving a presentation on monads next week, and hope you can help. (I'm not quite as lost as this might imply!) Q1: The web page mentions that normal Haskell functions cannot cause side-effects, yet later talks about side-effects with putStrLn. I assume the key point here that IO actions are, by definition, _not_ normal functions? Q2: Is it true to say that *any* monadic action *could *cause side-effects, depending on the design of that monad? i.e. Does one generalize from the IO monad to (possibly) an arbitrary monad? *Musing* This must be true as using State must surely be considered a side-effect. Q3: The web page mentions IO as being a baton, or token, that is used to thread/order the actions. Is true that this is merely one simple perspective, with respect to order of evaluation? This is hard to articulate, but it seems to me that "in the IO monad" there is a large subsystem of (inaccessible) state, machinery, etc. Is it really a token? Q4: Is the following idea accurate: a Haskell program is partitioned into 2 spaces. One is a sequence of IO actions; the other is a space of pure functions and 'normal' Haskell operations. The execution of a program begins with the main :: IO () action and, effectively, crosses from one space to the other. In the pure space, the math-like functions can be highly optimized but only insofar as they do not disrupt the implied order of the IO actions. Because of the type system, the program recognizes when it enters "back" into the IO space and follows different, less optimized rules. My concern is that the above is *not* accurate, but I don't know why. thanks so much for your help Michael Easter -- ---------------------- Michael Easter http://codetojoy.blogspot.com: Putting the thrill back in blog http://youtube.com/ocitv -> Fun people doing serious software engineering -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090227/9c250695/attachment.htm From wagner.andrew at gmail.com Fri Feb 27 22:30:39 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Fri Feb 27 22:19:29 2009 Subject: [Haskell-beginners] clarification on IO In-Reply-To: <1d393c9d0902271850i4b970c9dg43676ad34c77ff5f@mail.gmail.com> References: <1d393c9d0902271850i4b970c9dg43676ad34c77ff5f@mail.gmail.com> Message-ID: I'll take a shot at answering some of your questions by explaining how I understand it, and we'll see if it helps or makes it worse. Let's talk about monads first. Monads can be thought of as a way of sort of hiding "side effects". That is, there is nothing inherently impure about monads. The "side effects" happen in the bind function, essentiall. For example, in the case of state, the state is carried from one function to another. The bind function actually says how to do this; You just don't usually see it because it's "hidden" in the do notation. In the Maybe function, the plumbing hides the fact that we quit at any point the computation fails, and so on. So while in an impure language, any statement can have any side effect, in haskell, if you know what monad you're in, you know exactly what the "side effect" will occur - which means, it's not really a side effect at all, but part of the actual intended effect. Now for IO. You can think of IO as being essentially State RealWorld. That is, every operation is dependent on the entire state of the world, including what you're thinking, and what kind of bug is crawling on the 18th blade of grass in your yard. If we could actually represent the whole world this way, Haskell would truly be a completely pure language. The only reason IO, and thus Haskell, is impure at all, is because we can't literally represent the whole world. EVERYTHING ELSE, INCLUDING EVERY OTHER TYPE OF MONADIC ACTION IN HASKELL, is completely pure. Ok, so let's address your questions a little more specifically. Q1: The web page mentions that normal Haskell functions cannot cause > side-effects, yet later talks about > side-effects with putStrLn. I assume the key point here that IO actions > are, by definition, _not_ normal functions? > Right, IO actions can have side effects because they can take into account, and modify, the RealWorld. > Q2: Is it true to say that *any* monadic action *could *cause > side-effects, depending on the design of that > monad? i.e. Does one generalize from the IO monad to (possibly) an > arbitrary monad? *Musing* This must be true as > using State must surely be considered a side-effect. > Again, yes, this is accurate, but it's different from most impure languages in that the side effect is completely baked in by the monad you're in, so that you can't really say that the effect is a "side effect" at all. > Q3: The web page mentions IO as being a baton, or token, that is used to > thread/order the actions. Is true > that this is merely one simple perspective, with respect to order of > evaluation? This is hard to articulate, > but it seems to me that "in the IO monad" there is a large subsystem of > (inaccessible) state, machinery, etc. > Is it really a token? > Again, in many ways, it's easier to think of the IO monad as a state monad. In that sense, the state of the world is indeed being passed from one action to the next, as defined by bind. That's the inaccessible state machinery I suspect you're sensing. > Q4: Is the following idea accurate: a Haskell program is partitioned into 2 > spaces. One is a sequence > of IO actions; the other is a space of pure functions and 'normal' Haskell > operations. The execution of a > program begins with the main :: IO () action and, effectively, crosses from > one space to the other. In the > pure space, the math-like functions can be highly optimized but only > insofar as they do not disrupt the > implied order of the IO actions. Because of the type system, the program > recognizes when it enters > "back" into the IO space and follows different, less optimized rules. > I think it would be easier to talk about haskell in terms of pure and impure code. All Haskell code is pure except for IO. Pure functions are easier to reason about and to optimize, because you don't have to take into account the RealWorld state, or other possible, REAL side effects.. > My concern is that the above is *not* accurate, but I don't know why. > > > thanks so much for your help > Michael Easter > > -- > ---------------------- > Michael Easter > http://codetojoy.blogspot.com: Putting the thrill back in blog > > http://youtube.com/ocitv -> Fun people doing serious software engineering > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090227/15ec3af9/attachment-0001.htm From codetojoy at gmail.com Fri Feb 27 22:54:24 2009 From: codetojoy at gmail.com (Michael Easter) Date: Fri Feb 27 22:43:15 2009 Subject: [Haskell-beginners] clarification on IO In-Reply-To: References: <1d393c9d0902271850i4b970c9dg43676ad34c77ff5f@mail.gmail.com> Message-ID: <1d393c9d0902271954s75f4a972t2f20498207fb117b@mail.gmail.com> Thanks Andrew, this is really great... My main revelation here is that a "side-effect" in other monads is still pure. e.g. The Logger example in RWH builds up a list of log strings "behind the scenes" but this is much different than writing to disk, or launching missiles, to quote SP Jones. 'Revelation' is a good word.... The tectonic plates are coming together! I needed this. thanks! Mike ps. re: bind/hidden. Monads strike me as a glorious instance of encapsulation that is not OO, which appropriated the term in the 1990s. On Fri, Feb 27, 2009 at 9:30 PM, Andrew Wagner wrote: > I'll take a shot at answering some of your questions by explaining how I > understand it, and we'll see if it helps or makes it worse. > > Let's talk about monads first. Monads can be thought of as a way of sort of > hiding "side effects". That is, there is nothing inherently impure about > monads. The "side effects" happen in the bind function, essentiall. For > example, in the case of state, the state is carried from one function to > another. The bind function actually says how to do this; You just don't > usually see it because it's "hidden" in the do notation. In the Maybe > function, the plumbing hides the fact that we quit at any point the > computation fails, and so on. So while in an impure language, any statement > can have any side effect, in haskell, if you know what monad you're in, you > know exactly what the "side effect" will occur - which means, it's not > really a side effect at all, but part of the actual intended effect. > > Now for IO. You can think of IO as being essentially State RealWorld. That > is, every operation is dependent on the entire state of the world, including > what you're thinking, and what kind of bug is crawling on the 18th blade of > grass in your yard. If we could actually represent the whole world this way, > Haskell would truly be a completely pure language. The only reason IO, and > thus Haskell, is impure at all, is because we can't literally represent the > whole world. EVERYTHING ELSE, INCLUDING EVERY OTHER TYPE OF MONADIC ACTION > IN HASKELL, is completely pure. > > Ok, so let's address your questions a little more specifically. > > Q1: The web page mentions that normal Haskell functions cannot cause >> side-effects, yet later talks about >> side-effects with putStrLn. I assume the key point here that IO actions >> are, by definition, _not_ normal functions? >> > > Right, IO actions can have side effects because they can take into account, > and modify, the RealWorld. > > >> Q2: Is it true to say that *any* monadic action *could *cause >> side-effects, depending on the design of that >> monad? i.e. Does one generalize from the IO monad to (possibly) an >> arbitrary monad? *Musing* This must be true as >> using State must surely be considered a side-effect. >> > > Again, yes, this is accurate, but it's different from most impure languages > in that the side effect is completely baked in by the monad you're in, so > that you can't really say that the effect is a "side effect" at all. > > >> Q3: The web page mentions IO as being a baton, or token, that is used to >> thread/order the actions. Is true >> that this is merely one simple perspective, with respect to order of >> evaluation? This is hard to articulate, >> but it seems to me that "in the IO monad" there is a large subsystem of >> (inaccessible) state, machinery, etc. >> Is it really a token? >> > > Again, in many ways, it's easier to think of the IO monad as a state monad. > In that sense, the state of the world is indeed being passed from one action > to the next, as defined by bind. That's the inaccessible state machinery I > suspect you're sensing. > > >> Q4: Is the following idea accurate: a Haskell program is partitioned into >> 2 spaces. One is a sequence >> of IO actions; the other is a space of pure functions and 'normal' Haskell >> operations. The execution of a >> program begins with the main :: IO () action and, effectively, crosses >> from one space to the other. In the >> pure space, the math-like functions can be highly optimized but only >> insofar as they do not disrupt the >> implied order of the IO actions. Because of the type system, the program >> recognizes when it enters >> "back" into the IO space and follows different, less optimized rules. >> > > I think it would be easier to talk about haskell in terms of pure and > impure code. All Haskell code is pure except for IO. Pure functions are > easier to reason about and to optimize, because you don't have to take into > account the RealWorld state, or other possible, REAL side effects.. > > >> My concern is that the above is *not* accurate, but I don't know why. >> >> >> thanks so much for your help >> Michael Easter >> >> -- >> ---------------------- >> Michael Easter >> http://codetojoy.blogspot.com: Putting the thrill back in blog >> >> http://youtube.com/ocitv -> Fun people doing serious software engineering >> >> _______________________________________________ >> Beginners mailing list >> Beginners@haskell.org >> http://www.haskell.org/mailman/listinfo/beginners >> >> > -- ---------------------- Michael Easter http://codetojoy.blogspot.com: Putting the thrill back in blog http://youtube.com/ocitv -> Fun people doing serious software engineering -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090227/662f4e97/attachment.htm From will_n48 at yahoo.com Sat Feb 28 01:50:59 2009 From: will_n48 at yahoo.com (Will Ness) Date: Sat Feb 28 01:39:58 2009 Subject: [Haskell-beginners] Re: Defeating type inference References: <49A5DFC7.10507@foo.me.uk> Message-ID: Philip Scott foo.me.uk> writes: > > So I puzzled for a little bit about how to do this in the most Haskelly > way and I thought of this > > months = concat (range (Jan, Dec) : months) > > Which should work, right** > > ** though I am pretty sure this is the Wrong Way to do this. I suspect > concat takes O(n) time - more elegant approaches would be welcomed! > Nobody seem to relate to that point. No, it's not O(n) time. It's O(1) time. It's just one lazy definition. The _access_ is O(n) and the definition kicks in at the right time while riding along with the access - take, drop or whatever - along the list. It is always just taking one head element at a time off the first list, if not empty, or else switching to the next one - and feeding that element to list access. If it's not eliminated completely by compilation. :) From chaddai.fouche at gmail.com Sat Feb 28 04:13:49 2009 From: chaddai.fouche at gmail.com (=?UTF-8?B?Q2hhZGRhw68gRm91Y2jDqQ==?=) Date: Sat Feb 28 04:02:43 2009 Subject: [Haskell-beginners] clarification on IO In-Reply-To: <1d393c9d0902271850i4b970c9dg43676ad34c77ff5f@mail.gmail.com> References: <1d393c9d0902271850i4b970c9dg43676ad34c77ff5f@mail.gmail.com> Message-ID: On Sat, Feb 28, 2009 at 3:50 AM, Michael Easter wrote: > Q1: The web page mentions that normal Haskell functions cannot cause > side-effects, yet later talks about > side-effects with putStrLn. I assume the key point here that IO actions are, > by definition, _not_ normal functions? putStrLn is a perfectly pure function (there is no other kind in Haskell), it takes a String and return a value of type IO (), this value is like any other first class object in Haskell and can be manipulated as thus, the only difference is that this value can be computed in the context of the IO monad and then have a side-effect. The value of type IO a are often called actions but they aren't fundamentally different from other values. > Q2: Is it true to say that any monadic action could cause side-effects, > depending on the design of that > monad? i.e. Does one generalize from the IO monad to (possibly) an arbitrary > monad? *Musing* This must be true as > using State must surely be considered a side-effect. "Side-effect" isn't really appropriate in my opinion, since everything is still perfectly pure (except in IO) and the "effects" one obtain by using a monad are perfectly determined by the nature of the monad. > Q3: The web page mentions IO as being a baton, or token, that is used to > thread/order the actions. Is true > that this is merely one simple perspective, with respect to order of > evaluation? This is hard to articulate, > but it seems to me that "in the IO monad" there is a large subsystem of > (inaccessible) state, machinery, etc. > Is it really a token? This "token" is an useful concept to understand how the IO monad works, indeed that is how it is encoded in GHC where the IO monad is just a variant of the ST monad with a special type for the state : RealWorld. Of course the primitives used in the IO monad can't be written in pure Haskell. > Q4: Is the following idea accurate: a Haskell program is partitioned into 2 > spaces. One is a sequence > of IO actions; the other is a space of pure functions and 'normal' Haskell > operations.? The execution of a > program begins with the main :: IO () action and, effectively, crosses from > one space to the other. In the > pure space, the math-like functions can be highly optimized but only insofar > as they do not disrupt the > implied order of the IO actions.? Because of the type system, the program > recognizes when it enters > "back" into the IO space and follows different, less optimized rules. You can effectively see it like that, but it must be noted that the ordering of IO actions isn't special in any sense, it is just implied by the strict data dependence encoded in the monad, the compiler don't optimize differently the IO portion of the program. "main" is the only function that is evaluated unconditionally, any other value and/or function in a program is only evaluated if main needs it. -- Jeda? From dev at mobileink.com Sat Feb 28 05:30:52 2009 From: dev at mobileink.com (Gregg Reynolds) Date: Sat Feb 28 05:19:42 2009 Subject: [Haskell-beginners] clarification on IO In-Reply-To: <1d393c9d0902271850i4b970c9dg43676ad34c77ff5f@mail.gmail.com> References: <1d393c9d0902271850i4b970c9dg43676ad34c77ff5f@mail.gmail.com> Message-ID: <75cc17ac0902280230v28bfb5bfy171f4681a3e63e23@mail.gmail.com> On Fri, Feb 27, 2009 at 8:50 PM, Michael Easter wrote: > > > Q1: The web page mentions that normal Haskell functions cannot cause > side-effects, yet later talks about > side-effects with putStrLn. I assume the key point here that IO actions > are, by definition, _not_ normal functions? > Right, the IO primitives are not functions. > Q2: Is it true to say that *any* monadic action *could *cause > side-effects, depending on the design of that > monad? i.e. Does one generalize from the IO monad to (possibly) an > arbitrary monad? *Musing* This must be true as > using State must surely be considered a side-effect. > It might be helpful to distinguish between internal side effects (e.g. updating a global var in an imperative language) and external (IO). Haskell uses monads to simulate the former and to serialize the latter. > > > Q3: The web page mentions IO as being a baton, or token, that is used to > thread/order the actions. Is true > that this is merely one simple perspective, with respect to order of > evaluation? This is hard to articulate, > but it seems to me that "in the IO monad" there is a large subsystem of > (inaccessible) state, machinery, etc. > Is it really a token? > Bear in mind that's the GHC implementation. I'm told another implementation uses some kind of continuation monad. The only requirement as I understand it is that the IO monad, however it is designed, must impose an order of evaluation on the IO primitives. GHC does hide the implementation details. > > Q4: Is the following idea accurate: a Haskell program is partitioned into 2 > spaces. One is a sequence > of IO actions; the other is a space of pure functions and 'normal' Haskell > operations. The execution of a > program begins with the main :: IO () action and, effectively, crosses from > one space to the other. In the > pure space, the math-like functions can be highly optimized but only > insofar as they do not disrupt the > implied order of the IO actions. Because of the type system, the program > recognizes when it enters > "back" into the IO space and follows different, less optimized rules. > Hmm, to me there's something fishy about thinking in terms of two spaces. IO expressions are normal Haskell expressions; they just happen to get sequenced because they get chained together by monad ops. I.e. as far has Haskell semantics is concerned they're not special; Haskell needn't know they're impure. The impure part is external the Haskell semantics. Then remember lazy evaluation; the whole program can be optimized at compile time to some extent, and at run time evaluation is forced by the ordering of the "IO chain" that leads to main. Be careful about thinking of the program as "starting at main" and then proceeding through the IO chain. That's perilously close to imperative thinking. It's more accurate (IMO) to say that the program gets evaluated at run time, which means main gets evaluated, and since the value of main depends on the series of IO actions chained to it, they get forced in order. So main isn't really the "first thing that happens"; it's the ONLY thing that happens, since the meaning of the program (i.e. main) is equivalent to the evaluation of the IO chain. Actual IO is a side effect of evaluating main. Hope it helps, gregg -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090228/a3c4a077/attachment-0001.htm From j.romildo at gmail.com Sat Feb 28 06:27:45 2009 From: j.romildo at gmail.com (j.romildo@gmail.com) Date: Sat Feb 28 10:54:19 2009 Subject: [Haskell-beginners] Non-recursive binding expression Message-ID: <20090228112745.GA22618@darling.DHCP-GERAL> Hello. Is there any non-recursive binding expression in Haskell? Something that would allow me to write, for instance, test = let' xs = [] in let' xs = 3 : xs in let' xs = 8 : xs in let' xs = 7 : xs in xs Here let' is an hypothetical construction similar to let, except that it would be non-recursive. In the example, the value of test would be [7,8,3]. So, is there something in this line in Haskell? Regards, Jos? Romildo From will_n48 at yahoo.com Sat Feb 28 12:19:03 2009 From: will_n48 at yahoo.com (Will Ness) Date: Sat Feb 28 12:08:08 2009 Subject: [Haskell-beginners] Re: Non-recursive binding expression References: <20090228112745.GA22618@darling.DHCP-GERAL> Message-ID: gmail.com> writes: > > Hello. > > Is there any non-recursive binding expression in Haskell? > > Something that would allow me to write, for instance, > > test = let' xs = [] in > let' xs = 3 : xs in > let' xs = 8 : xs in > let' xs = 7 : xs in > xs > > Here let' is an hypothetical construction similar to let, except that it > would be non-recursive. In the example, the value of test would be > [7,8,3]. > > So, is there something in this line in Haskell? > > Regards, > > Jos? Romildo > Well, it's not a nice thing to do (probably), but you can write test = head $ do xs <- [ [] ] xs <- [ 3:xs ] xs <- [ 8:xs ] xs <- [ 7:xs ] return xs From byorgey at seas.upenn.edu Sat Feb 28 13:01:56 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Sat Feb 28 12:50:44 2009 Subject: [Haskell-beginners] Re: Non-recursive binding expression In-Reply-To: References: <20090228112745.GA22618@darling.DHCP-GERAL> Message-ID: <20090228180155.GA2073@seas.upenn.edu> On Sat, Feb 28, 2009 at 05:19:03PM +0000, Will Ness wrote: > gmail.com> writes: > > > > > Hello. > > > > Is there any non-recursive binding expression in Haskell? > > > > Something that would allow me to write, for instance, > > > > test = let' xs = [] in > > let' xs = 3 : xs in > > let' xs = 8 : xs in > > let' xs = 7 : xs in > > xs > > Well, it's not a nice thing to do (probably), but you can write > > test = head $ > do xs <- [ [] ] > xs <- [ 3:xs ] > xs <- [ 8:xs ] > xs <- [ 7:xs ] > return xs > The correct answer is no. Life is pain. Anyone who says otherwise is selling something. ;) Assignment in Haskell is not destructive update---it assigns a name to a value, and they become one flesh, until parted by death (i.e. the end of their lexical scope). The only reason Will's code works is that each line creates a new lexical scope, and each xs shadows the previous one. To do what you want, you have to give each thing a new name, something like this: test = let xs = [] xs' = 3 : xs xs'' = 8 : xs' xs''' = 7 : xs'' in xs''' "But this is horribly painful!" you cry. Of course it is! Giving names to things you don't want to keep is always painful (like when your child names the almost-dead raccoon you find in the street, which is just going to die or be given to an animal shelter anyway). So, why not just avoid naming things you don't want? test = (7:) . (8:) . (3:) $ [] Ah, that's better! We just thread some intermediate values through a chain of composed functions. Each function does its little bit of modification and passes the intermediate value along to the next function, and the intermediate values are never given names. -Brent From will_n48 at yahoo.com Sat Feb 28 14:13:01 2009 From: will_n48 at yahoo.com (Will Ness) Date: Sat Feb 28 14:01:59 2009 Subject: [Haskell-beginners] Re: clarification on IO References: <1d393c9d0902271850i4b970c9dg43676ad34c77ff5f@mail.gmail.com> Message-ID: Michael Easter gmail.com> writes: > > > Q1: The web page mentions that normal Haskell functions cannot cause side- effects, yet later talks about > side-effects with putStrLn. I assume the key point here that IO actions are, by definition, _not_ normal functions? The way I look at it, a monad is a way of saying, "we'll be carrying along and combining, in some specific manner, values with some extra information attached to them, which most functions don't need to worry about". _How_ it carries along these values and combines them, and the corresponding hidden data, is what makes the particular Monad type to be what it is. Let's call a function an M-action function if its type is (:: a -> M b), for some monad M. Such functions can get chained by M's bind, as in ( (x :: M a) >>= (f :: a -> M b) ) :: M b M can also provide us with special functions that will reveal its hidden information, e.g. (reveal :: (hidden_stuff -> a -> M b) -> a -> M b), so that for a user-defined (g :: hidden_stuff -> a -> M b), (reveal g) can be chained and the function g will get called providing us with the information, if the monad so chooses. For example, Philip Wadler in his paper "The Essence of Functional Programming" gives an example of a "position" monad P which defines its own special function, resetPosition, enabling us to reset its hidden data - in this case, a code position. IO primitives like putStrLn, instead of revealing anything to us, carry along a promise to take notice of the value they are supplied with and to perform an actual real world IO action with them, when called upon to do so by the system. We can create chains of IO-action functions and store them in variables, without them getting executed by the system - and thus without causing any real- world IO action, e.g. x = do {putStrLn "1";return 2} somewhere in your program will just create a definition that will just hold an IO-action function in it. It's just a feature of an interactive loop that when is sees a value of type (IO a) it will not just return it, but will also execute the promised actions held inside it: -- in HUGS -- Prelude> [ do {putStrLn "1";return 2} ] -- a value just gets returned [<>] :: [IO Integer] Prelude> do {putStrLn "1";return 2} -- actual IO action performed 1 :: IO Integer -- in GHCi -- Prelude> let x=[do {putStrLn "1"; return 2}] Prelude> head x 1 2 Prelude> head x 1 2 Prelude> :t it it :: Integer The same goes to the special identifier (main :: IO a) that will also get treated in this special way - getting executed on sight. :) From tom.davie at gmail.com Sat Feb 28 14:40:46 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Sat Feb 28 14:29:35 2009 Subject: [Haskell-beginners] clarification on IO In-Reply-To: References: <1d393c9d0902271850i4b970c9dg43676ad34c77ff5f@mail.gmail.com> Message-ID: On 28 Feb 2009, at 10:13, Chadda? Fouch? wrote: > On Sat, Feb 28, 2009 at 3:50 AM, Michael Easter > wrote: >> Q1: The web page mentions that normal Haskell functions cannot cause >> side-effects, yet later talks about >> side-effects with putStrLn. I assume the key point here that IO >> actions are, >> by definition, _not_ normal functions? > > putStrLn is a perfectly pure function (there is no other kind in > Haskell), it takes a String and return a value of type IO (), this > value is like any other first class object in Haskell and can be > manipulated as thus, the only difference is that this value can be > computed in the context of the IO monad and then have a side-effect. > The value of type IO a are often called actions but they aren't > fundamentally different from other values. Note, take this information with a pretty gigantic grain of salt. It is true that you are writing a pure program when using IO functions, but you should probably think about what that means. The advantage of pure programs is that you get certain neat benefits like not having to bother about "am I doing this in the right order" or "will the system do weird random shit while this function is executed". This is not true about IO typed functions. An IO typed function generates an IO value which the runtime runs. That means, that they essentially get us no further forward than C. In C we write pure functions called C preprocessor macros. These pure functions generate imperative programs (C programs) which are run by the runtime (the C compiler and your OS). This is no different to IO. So, the lesson ? IO is in theory pure. But that doesn't mean that we get all the nice benefits of functional programming while using the IO monad. One can say pretty much the same thing about all stateful monads, although IO is by far the worse, in that the state can be influenced by chunks of reality totally outside your control. Bob From bbb.lst at gmail.com Sat Feb 28 15:57:41 2009 From: bbb.lst at gmail.com (Bjoern Brandenburg) Date: Sat Feb 28 15:46:28 2009 Subject: [Haskell-beginners] Catching Exceptions in Haskell Message-ID: <7ba288b20902281257x63b6631bkbbc5a69d57baf8d9@mail.gmail.com> Hi all, I'm struggling to figure out how to catch an exception in Haskell. Eventually, what I want to do is to use the Control.Macho library (from Hackage) to parse binaries on Mac OS X. Naturally, I would like my program to gracefully handle corrupted files or files that aren't binaries. So I need to catch exceptions if the parsing with Data.Macho fails... This is what I've got so far: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=1877#a1877 Digression: Note that if I leave out the `foo e` call, then I get scratch.hs:21:9: Ambiguous type variable `e' in the constraint: `Exception e' arising from a use of `try' at scratch.hs:21:9-11 Probable fix: add a type signature that fixes these type variable(s) I find this somewhat counter-intuitive; this is also not discussed in the book "Real-World Haskell" (at least I haven't found it), which is what I'm using to learn Haskell. What is the best way to get around this? Back to my problem. The program produces the following output: $ runghc scratch.hs Testing Pure... Caught a bad exception: abort via error Testing Macho... No exception occured, the result is: scratch.hs: too few bytes. Failed reading at byte position 4 This counter-intuitive in at least two ways: 1) How can it fail at position 4 in an empty string? That looks like a sloppy error message too me; why doesn't it report the actually failing position? 2) Why can I catch an exception raised with an error in my own code, but not the one raised by Data.Binary.Get? Looking at http://hackage.haskell.org/packages/archive/binary/0.5/doc/html/src/Data-Binary-Get.html#failDesc , an exception within Data.Binary.Get is also raised with error. What is the difference? Why am I seeing what I'm seeing, and how should I be doing it in the first place? Thanks in advance, Bjoern From will_n48 at yahoo.com Sat Feb 28 17:31:37 2009 From: will_n48 at yahoo.com (Will Ness) Date: Sat Feb 28 17:20:34 2009 Subject: [Haskell-beginners] Re: Non-recursive binding expression References: <20090228112745.GA22618@darling.DHCP-GERAL> <20090228180155.GA2073@seas.upenn.edu> Message-ID: Brent Yorgey seas.upenn.edu> writes: > > On Sat, Feb 28, 2009 at 05:19:03PM +0000, Will Ness wrote: > > gmail.com> writes: > > > > > > > > Hello. > > > > > > Is there any non-recursive binding expression in Haskell? > > > > > > Something that would allow me to write, for instance, > > > > > > test = let' xs = [] in > > > let' xs = 3 : xs in > > > let' xs = 8 : xs in > > > let' xs = 7 : xs in > > > xs > > > > Well, it's not a nice thing to do (probably), but you can write > > > > test = head $ > > do xs <- [ [] ] > > xs <- [ 3:xs ] > > xs <- [ 8:xs ] > > xs <- [ 7:xs ] > > return xs > > > > The correct answer is no. Life is pain. Anyone who says otherwise is > selling something. ;) > > Assignment in Haskell is not destructive update---it assigns a name to > a value, and they become one flesh, until parted by death (i.e. the > end of their lexical scope). The only reason Will's code works is > that each line creates a new lexical scope, and each xs shadows the > previous one. That's what I understood the OP wanted - Scheme's LET, not LETREC, allowing for shadowing. I was suprised let-statement in do chain didn't work that way. I expected it to be equivalent to a kind of code above, since each new line in do block represents a nested function in explicit bind notation, and nested function binding definitely provides for non-recursive let kind of argument binding, with shadowing. I thought the whole point of having special let statement in do notation was not to have to write the kind of code above with singleton lists. Since we have shadowing there, it should've been so in let-statements too. Isn't it? > > To do what you want, you have to give each thing a new name, something > like this: > > test = let xs = [] > xs' = 3 : xs > xs'' = 8 : xs' > xs''' = 7 : xs'' > in xs''' > > "But this is horribly painful!" you cry. Of course it is! Giving > names to things you don't want to keep is always painful (like when > your child names the almost-dead raccoon you find in the street, which > is just going to die or be given to an animal shelter anyway). > > So, why not just avoid naming things you don't want? > > test = (7:) . (8:) . (3:) $ [] > > Ah, that's better! We just thread some intermediate values through a > chain of composed functions. Each function does its little bit of > modification and passes the intermediate value along to the next > function, and the intermediate values are never given names. > > -Brent > BTW could there be a use for something like infixl 1 # x # f = f x -- (#) = flip ($) to have the direct data flow reflected in our code, so that your code would become test = [] # (3:) # (8:) # (7:) maybe sometimes it's more natural to think of data being "piped through" the chain of functions, and to write them down in forward, not reverse order of application? From es at ertes.de Sat Feb 28 18:44:31 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Sat Feb 28 18:33:48 2009 Subject: [Haskell-beginners] Re: Non-recursive binding expression References: <20090228112745.GA22618@darling.DHCP-GERAL> <20090228180155.GA2073@seas.upenn.edu> Message-ID: <20090301004431.73cd0856@tritium.xx> Will Ness wrote: > BTW could there be a use for something like > > infixl 1 # > > x # f = f x -- (#) = flip ($) > > to have the direct data flow reflected in our code, so that your code > would become > > test = [] # (3:) # (8:) # (7:) > > maybe sometimes it's more natural to think of data being "piped > through" the chain of functions, and to write them down in forward, > not reverse order of application? I think, it's more natural to think in terms of functions, and often the argument to a function is not just something as simple as [] anyway. If you want to think in chaining instead of composition, you can use arrow sequencing (>>>) instead of function composition (.): import Control.Arrow test = (3:) >>> (8:) >>> (7:) $ [] Greets, Ertugrul. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/ From byorgey at seas.upenn.edu Sat Feb 28 19:10:47 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Sat Feb 28 18:59:35 2009 Subject: [Haskell-beginners] Re: Non-recursive binding expression In-Reply-To: References: <20090228112745.GA22618@darling.DHCP-GERAL> <20090228180155.GA2073@seas.upenn.edu> Message-ID: <20090301001047.GA11431@seas.upenn.edu> On Sat, Feb 28, 2009 at 10:31:37PM +0000, Will Ness wrote: > > That's what I understood the OP wanted - Scheme's LET, not LETREC, allowing for > shadowing. I was suprised let-statement in do chain didn't work that way. I > expected it to be equivalent to a kind of code above, since each new line in do > block represents a nested function in explicit bind notation, and nested > function binding definitely provides for non-recursive let kind of argument > binding, with shadowing. > > I thought the whole point of having special let statement in do notation was > not to have to write the kind of code above with singleton lists. Since we have > shadowing there, it should've been so in let-statements too. Isn't it? No, the point of let expressions in do-blocks is to have a convenient way to make pure bindings, i.e. ones that aren't piped through >>= . Note that let statements in do-blocks just get desugared into normal let expressions: do { let x = y ; stuff } desugars into let x = y in do { stuff } Haskell simply doesn't have anything equivalent to Scheme's LET, except for actual nested functions. -Brent From bbb.lst at gmail.com Sat Feb 28 19:48:19 2009 From: bbb.lst at gmail.com (Bjoern Brandenburg) Date: Sat Feb 28 19:37:06 2009 Subject: [Haskell-beginners] Re: Catching Exceptions in Haskell In-Reply-To: <7ba288b20902281257x63b6631bkbbc5a69d57baf8d9@mail.gmail.com> References: <7ba288b20902281257x63b6631bkbbc5a69d57baf8d9@mail.gmail.com> Message-ID: <7ba288b20902281648k26f27114n832d78684d84805a@mail.gmail.com> Ok, so I was able to extract a simpler program with the same symptoms. http://hpaste.org/fastcgi/hpaste.fcgi/view?id=1900#a1900 Apparently the exception is only triggered when m is used in line 31. So I guess that evaluate in line 24 is not causing strict evaluation of the Data.Binary.Get monad, even though it is working for the error and assert tests. Why is that? Is that expected? If so, what am I doing wrong? Thanks, Bjoern From bugfact at gmail.com Sat Feb 28 21:16:13 2009 From: bugfact at gmail.com (Peter Verswyvelen) Date: Sat Feb 28 21:05:01 2009 Subject: [Haskell-beginners] Re: Catching Exceptions in Haskell In-Reply-To: <7ba288b20902281648k26f27114n832d78684d84805a@mail.gmail.com> References: <7ba288b20902281257x63b6631bkbbc5a69d57baf8d9@mail.gmail.com> <7ba288b20902281648k26f27114n832d78684d84805a@mail.gmail.com> Message-ID: The 3rd exception is raised when (show m) is computed, since no exception occurred when evaluating (testGet L.empty) itself. When you call "evaluate?a", it only forces "one level" of?evaluation of a. E.g. if you would run > evaluate (1:error "2":[]) >>= print . head this would print 1, and not give an error. You can maybe understand this better when you change > (res :: Either SomeException String) <- try $ evaluate (f x) into > (res :: Either SomeException String) <- try $ return (f x) Now the 2nd exception won't be raised either: evaluate digged one level into assert, and that causes an exception, but return will not do that, it will just return the unevaluated thunk that wraps the assert computation, and this thunk will get evaluated when you print it You can get the behavior what you expect by using some functions from Control.Parallel.Strategies. Change (res :: Either SomeException String) <- try $ evaluate (f x) into (res :: Either SomeException String) <- try $?evaluate?(f x `using` rnf) Now all 3 will throw an exception, as you expected.?Why? (a `using` rnf) reduces its argument (a) to "head normal form", which basically means it evaluating all sub-expressions at all levels. So > evaluate (1:error "2":[] `using` rnf) >>= print . head will now give an error. Cheers, Peter Verswyvelen On Sun, Mar 1, 2009 at 1:48 AM, Bjoern Brandenburg wrote: > > Ok, so I was able to extract a simpler program with the same symptoms. > > http://hpaste.org/fastcgi/hpaste.fcgi/view?id=1900#a1900 > > Apparently the exception is only triggered when m is used in line 31. > So I guess that evaluate in line 24 is not causing strict evaluation > of the Data.Binary.Get monad, even though it is working for the error > and assert tests. > > Why is that? Is that expected? If so, what am I doing wrong? > > Thanks, > Bjoern > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners From j.romildo at gmail.com Sat Feb 28 17:02:25 2009 From: j.romildo at gmail.com (j.romildo@gmail.com) Date: Sat Feb 28 21:18:30 2009 Subject: [Haskell-beginners] Re: Non-recursive binding expression In-Reply-To: <20090228180155.GA2073@seas.upenn.edu> References: <20090228112745.GA22618@darling.DHCP-GERAL> <20090228180155.GA2073@seas.upenn.edu> Message-ID: <20090228220225.GA4569@darling.DHCP-GERAL> On Sat, Feb 28, 2009 at 01:01:56PM -0500, Brent Yorgey wrote: > On Sat, Feb 28, 2009 at 05:19:03PM +0000, Will Ness wrote: > > gmail.com> writes: > > > > > > > > Hello. > > > > > > Is there any non-recursive binding expression in Haskell? > > > > > > Something that would allow me to write, for instance, > > > > > > test = let' xs = [] in > > > let' xs = 3 : xs in > > > let' xs = 8 : xs in > > > let' xs = 7 : xs in > > > xs > > > > Well, it's not a nice thing to do (probably), but you can write > > > > test = head $ > > do xs <- [ [] ] > > xs <- [ 3:xs ] > > xs <- [ 8:xs ] > > xs <- [ 7:xs ] > > return xs > > > > The correct answer is no. Life is pain. Anyone who says otherwise is > selling something. ;) > > Assignment in Haskell is not destructive update---it assigns a name to > a value, and they become one flesh, until parted by death (i.e. the > end of their lexical scope). The only reason Will's code works is > that each line creates a new lexical scope, and each xs shadows the > previous one. I am not asking for assignment. What I want is indeed what I already said: a new lexical scope which introduces a new variable, but the variable name is being reused. That shadows the previous definition. What I want is the possibilitiy of a non-recursive binding expression, like my hypothecial let' construction. Being non-recursive, let' = in any occurrence of in does not refer to the new varibale being introduced, but to some previous defined variable named . If that does exist, than there is a semantic error in the expression (unless is not used in , of course). So the scope of is just . It does not include . If it was a recursive definition, the scope of would be *and* . Romildo From poliquin at softcomp.com Sat Feb 28 21:36:22 2009 From: poliquin at softcomp.com (Tom Poliquin) Date: Sat Feb 28 22:02:08 2009 Subject: [Haskell-beginners] Finite State Machine .. Message-ID: <200902281836.22114.poliquin@softcomp.com> I'm working on a project (in Haskell) and was given some old Java code to indicate the required functionality for a particular function. It's a page of nested (4 deep) if statements. (That's probably why they gave me the code, no one could describe it). I would normally convert this to an FSM, ..... but this is Haskell! So, 1) Is there a nice (canonical) way of eliminating nested evil in Haskell? I thought that perhaps making a tuple of all the if's conditions and patterm matching on them might make a bit more comprehensible. Likely there's a better way. 2) If an FSM is appropriate is there a 'standard' Haskell FSM implementation? I looked around and could find very little. One paper talked about Arrows but that seems like a bit of overkill .. It actually seems like a fun problem .. if I had the time .. Any thoughts greatly appreciated! Tom From wagner.andrew at gmail.com Sat Feb 28 22:17:36 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Sat Feb 28 22:06:23 2009 Subject: [Haskell-beginners] Finite State Machine .. In-Reply-To: <200902281836.22114.poliquin@softcomp.com> References: <200902281836.22114.poliquin@softcomp.com> Message-ID: This does sound interesting. Can you provide (at least some of) the code? On Sat, Feb 28, 2009 at 9:36 PM, Tom Poliquin wrote: > > I'm working on a project (in Haskell) and was > given some old Java code to indicate the required > functionality for a particular function. It's a page of > nested (4 deep) if statements. (That's probably > why they gave me the code, no one could > describe it). > > I would normally convert this to an FSM, > ..... but this is Haskell! > > So, > > 1) Is there a nice (canonical) way of eliminating > nested evil in Haskell? I thought that perhaps making > a tuple of all the if's conditions and patterm matching > on them might make a bit more comprehensible. > Likely there's a better way. > > 2) If an FSM is appropriate is there a 'standard' > Haskell FSM implementation? > I looked around and could find very little. One > paper talked about Arrows but that seems like a bit > of overkill .. > > It actually seems like a fun problem .. if I > had the time .. > > Any thoughts greatly appreciated! > > > Tom > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090228/4b918e51/attachment.htm From bbb.lst at gmail.com Sat Feb 28 22:17:49 2009 From: bbb.lst at gmail.com (Bjoern Brandenburg) Date: Sat Feb 28 22:06:36 2009 Subject: [Haskell-beginners] Re: Catching Exceptions in Haskell In-Reply-To: References: <7ba288b20902281257x63b6631bkbbc5a69d57baf8d9@mail.gmail.com> <7ba288b20902281648k26f27114n832d78684d84805a@mail.gmail.com> Message-ID: <7ba288b20902281917t5cfda8d4of687b68658a33e8a@mail.gmail.com> On Sat, Feb 28, 2009 at 9:16 PM, Peter Verswyvelen wrote: > When you call "evaluate?a", it only forces "one level" of?evaluation of a. I missed this fact when reading the documentation about evaluate. Thank you for your explanation. - Bjoern