Re: [Haskell-cafe] some way to reverse engineer lambda expressionsout of the debugger?
works like a charm :) 2007/1/11, Claus Reinke [EMAIL PROTECTED]: Looks very nice! thanks!-) it is far from a full-blown solution to the question in the subject, but it has its uses. However, I'm doing my learning on ghci and got an error when I tried to load it. Is this hugs only, or should I try harder? I was using Hugs when I wrote that, but it works in GHC almost as well. the error message really ought to point to the option needed, which is -fglasgow-exts if you don't want to set the options by hand, just add the following pragma to the top of R.hs: {-# OPTIONS_GHC -fglasgow-exts #-} more annoying is that ghci will ignore the default directive, so you'll need to give explicit types when you want representations: *Main foldr (+) 0 [1..4] 10 *Main foldr (+) 0 [1..4] :: R Int (1 + (2 + (3 + (4 + 0 *Main map (*) [1,2] interactive:1:0: No instance for (Show (t - t)) arising from use of `print' at interactive:1:0-12 Possible fix: add an instance declaration for (Show (t - t)) In the call (print it) In the expression: print it In a 'do' expression: print it *Main map (*) [1,2] :: [R Int - R Int] [\x-(1 * x),\x-(2 * x)] claus 2007/1/11, Malcolm Wallace [EMAIL PROTECTED]: Bulat Ziganshin [EMAIL PROTECTED] wrote: tphyahoo wrote: *UnixTools explodeLambda( map (*) [1,2] ) [(\x - 1*x),(\x - 2*x)] Have a play with this, from Claus Reinke: http://www.cs.kent.ac.uk/people/staff/cr3/toolbox/haskell/R.hs Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Re: Monad Set via GADT
| On 1/3/07, Roberto Zunino [EMAIL PROTECTED] wrote: | 1) Why the first version did not typececk? | 1) Class constraints can't be used on pattern matching. They ARE | restrictive on construction, however. This is arguably bug in the | Haskell standard. It is fixed in GHC HEAD for datatypes declared in | the GADT way, so as not to break H98 code: | | http://article.gmane.org/gmane.comp.lang.haskell.cvs.all/29458/match=gadt+class+context | | To quote from there: I think this is stupid, but it's what H98 says. | | Maybe it is time to consider it deprecated to follow the Haskell 98 | standard /to the letter/. GHC follows this strange standard when you write data type decls in H98 form data Eq a = T a = C a Int | D Here, pattern-matching on either C or D will cause an (Eq a) constraint to be required. However, GHC does *not* follow this convention when you write the data type decl in GADT style syntax: data T a where C :: Eq a = a - Int - T a D :: T a Here, (a) you can be selective; in this case, C has the context but D does not. And (b) GHC treats the constraints sensibly: - (Eq a) is *required* when C is used to construct a value - (Eq a) is *provided* when C is used in pattern matching In short, in GADT-style syntax, GHC is free to do as it pleases, so it does the right thing. In this case, then, you can avoid the H98 bug by using GADT-style syntax. All of this is documented in the user manual. If it's not clear, please help me improve it. Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: readFile problem
Hi, I finally found and solved the problem. The problem was in a small library I wrote which handles threads. When a thread executed its error handler, it started to kill (with throwTo) all other threads in the group he belongs to. Unfortunately all other threads started their error handlers too and started killing all other threads (again). The resulting thunderstorm of throwTos lead to the strange behaviour I observed. regards Stefan 2007/1/8, Stefan Aeschbacher [EMAIL PROTECTED]: Hi I am writing a network server in haskell. Lately I seem to have introduced a new bug. On Linux, when a client closes the connection to the server, the server dumps core. On Windows, the error message there is way different from the core dump on Linux. It says: application.exe: config.xml: openFile: does not exist (No such file or directory) I use readFile to read the config file. I tried to print out the config file after it is read to make sure that it is completely read. I only load this config file exactly once during program initialization. The config is used long before the crash. I printed the current working dir in the exception handler and there is something interesting. Instead of the path to the application, it is \C:\\WINDOWS\\system32. There are many things i do not understand. Why the different behaviour on Linux and Windows? Shouldn't an exception be thrown on Linux instead of a core dump? I don't use any unsafePerformIO or foreign calls. Why the changed path? I never change working directory in my code. Why is a function (- reading the config file) re-evaluated at a later point in time? How can I debug such a problem? My environement is ghc 6.6 on Ubuntu or Windows XP. thanks for any ideas Stefan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] State monad strictness - how?
John Meacham wrote: incidentally, I made a very strict and unboxed version of the RWS monad, since it is a darn useful one in jhc. right now, it only implements the things I needed, but it might be useful to include somewhere common and expanded on http://repetae.net/dw/darcsweb.cgi?r=jhc;a=headblob;f=/Util/RWS.hs John I have copied your email and the code to the wiki at http://haskell.org/haskellwiki/New_monads/UnboxedRWS and linked to it from the page that collects such items: http://haskell.org/haskellwiki/New_monads Everyone who is discussing variants of State might consider posting useful implementations on the wiki under New_monads. For example, some time ago I posted a LazyWriterT that added the '~' to the tuple matching in (=) and mfix. -- Chris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Monad Set via GADT
On Friday 12 January 2007 09:04, Simon Peyton-Jones wrote: | On 1/3/07, Roberto Zunino [EMAIL PROTECTED] wrote: | 1) Why the first version did not typececk? | | 1) Class constraints can't be used on pattern matching. They ARE | restrictive on construction, however. This is arguably bug in the | Haskell standard. It is fixed in GHC HEAD for datatypes declared | in the GADT way, so as not to break H98 code: | | http://article.gmane.org/gmane.comp.lang.haskell.cvs.all/29458/matc |h=gadt+class+context | | To quote from there: I think this is stupid, but it's what H98 | says. | | Maybe it is time to consider it deprecated to follow the Haskell 98 | standard /to the letter/. GHC follows this strange standard when you write data type decls in H98 form data Eq a = T a = C a Int | D Here, pattern-matching on either C or D will cause an (Eq a) constraint to be required. However, GHC does *not* follow this convention when you write the data type decl in GADT style syntax: data T a where C :: Eq a = a - Int - T a D :: T a Here, (a) you can be selective; in this case, C has the context but D does not. And (b) GHC treats the constraints sensibly: - (Eq a) is *required* when C is used to construct a value - (Eq a) is *provided* when C is used in pattern matching In short, in GADT-style syntax, GHC is free to do as it pleases, so it does the right thing. In this case, then, you can avoid the H98 bug by using GADT-style syntax. All of this is documented in the user manual. If it's not clear, please help me improve it. Crystal clear. My remark was meant merely as a general observation. Cheers Ben ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: advice on architecting a library (and haskell software in general)
Yang wrote: hi all, i'm looking for advice on how to architect a simple widget library for vty/hscurses, but these beginner-level questions should apply to haskell applications in general. input/requests on any aspect of my design would be greatly appreciated - in return perhaps you'll get something you'd actually want to use! i have studied in detail various haskell curses/vty apps, including yi, hmp3, riot, and hscurses.widgets/contactmanager. my immediate goal is to produce a set of composable widgets and a flexible framework that - as much as possible - reduces the amount of code a user has to write. my eventual goal is to make a functional gui library, along the lines of fruit/wxfruit/fg. to this end i've also read their literature, but i still do not understand enough about arrows/yampa/afrp. Currently, the design of a functional UI library (be it graphical or for tty) is still an open research problem. Somehow, the arrow based approaches like Fruit etc. are not yet satisfying. A predecessor to this approach is FranTk. The early library Fudgets is in essence based on arrows but precedes their invention. The most recent development in this direction is Phooey. In the mean time, the medium level libraries wxHaskell and gtk2hs have gathered acceptance, mostly because they implement a full widget set while still being reasonably succinct. A predecessor is HToolkit drawing from ObjectIO. Despite being close to their imperative cousins, they already supersede them in expressiveness. They make an excellent base for further experiments, be it for arrows (wxFruit) or other recent approaches like PropLang. You have two options: * Search for the grail. Most likely, this doesn't involve much coding but much searching and has the risk of not finding it. But as the tty doesn't have many different widgets, you can concentrate on the high level ideas, i.e. how to get rid of IO and IORefs. Pumping your brain with ideas - as you already do - surely helps. * Implement an existing design. This way, you'll actually program something. I'd propose to implement something medium level along the lines of wxHaskell that can later be utilized in a high level approach. Maybe you can even create a cross platform interface, i.e. one that works for a tty and for graphical UIs at the same time. The author of HToolkit wrote a proposal on how to transparently enclose Windows, Mac and Gnome. try to use it for a real application that has little to do with parsing or other purported strengths of the language. Well, Haskell's only strength is that it gives you enough power to express your ideas, i.e. to compose great things from small ones. The strength of your ideas is your business :) In this sense, monadic parser combinators are not an inherent strength of the language, they happen to be powerful by themselves. Regards, apfelmus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] MissingH: profiler support?
Thanks, this works! I had to build all the other libraries that are required with profiling support too. I also wrote it down on the MissingH wiki, see http://software.complete.org/missingh/wiki/Profiling -chris On 12 Jan, 2007, at 4:08 , Spencer Janssen wrote: The typical way to add profiling support to a Cabal lib is to add - p at configure time (ie runhaskell Setup.hs configure -p). Have you tried this? Cheers, Spencer Janssen On Jan 8, 2007, at 4:13 PM, Chris Eidhof wrote: Hey all, I'm trying to profile my application, which makes use of MissingH. But when compiling with -prof -auto-all, I get the following error: Language.hs:8:7: Could not find module `Data.String': Perhaps you haven't installed the profiling libraries for package MissingH-0.18.0? Use -v to see a list of the files searched for. When compiling without those options, everything works just fine. I built missingh from source, and added -prof -auto-all to GHCPARMS, and did a ./setup configure,make,install and still no result. Does anyone know what could be wrong? I'd really like to keep using MissingH and having profiling support at the same time. Thanks, -chris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Resending: MissingH: profiler support?
Hi John, On Jan 11, 2007, at 8:06 PM, John Goerzen wrote: On 2007-01-11, Chris Eidhof [EMAIL PROTECTED] wrote: Hey, does anyone know about this? Resending as I got no replies (yet) ;) Just for the record, I have no idea; I've never really used profiling and couldn't figure out how to make it work in general (at least not in a short amount of time). Are you sure your problem is restricted to MissingH? I can't think of anything special about it that would throw off profiling. -- John Does MissingH's cabal file have a line Ghc-Prof-Options: -prof -auto-all ? The rhs of the option is added to compiler command line when the --enable-library-profiling option is included to configure. Without this, the --enable-library-profiling switch doesn't do anything. (Arguably a bug that cabal silently does nothing instead of reporting an error.) Best Wishes, Greg ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Resending: [Haskell-cafe] MissingH: profiler support?
On Thu, 11 Jan 2007, Chris Eidhof [EMAIL PROTECTED] wrote: On 8 Jan, 2007, at 23:13 , Chris Eidhof wrote: I'm trying to profile my application, which makes use of MissingH. But when compiling with -prof -auto-all, I get the following error: Language.hs:8:7: Could not find module `Data.String': Perhaps you haven't installed the profiling libraries for package MissingH-0.18.0? Use -v to see a list of the files searched for. Use Cabal to compile and install the profiling libraries. There is a flag called --enable-profiling, or something like that. If you use GHC you will get two libraries, one without profiling, and one with, but that is a technical detail that Cabal takes care of. Just use the flag, and things should work. -- /NAD ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Resending: MissingH: profiler support?
On Fri, Jan 12, 2007 at 08:10:47AM -0500, Gregory Wright wrote: -- John Does MissingH's cabal file have a line Ghc-Prof-Options: -prof -auto-all No, it doesn't. None of my Cabal files do. Could anyone confirm if this fixes it? The rhs of the option is added to compiler command line when the --enable-library-profiling option is included to configure. Without this, the --enable-library-profiling switch doesn't do anything. (Arguably a bug that cabal silently does nothing instead of reporting an error.) I'd argue that Cabal should make this a default. It seems silly to have to add this boilerplate code to every cabal file out there just to have a sensible default. Thanks for the info. -- John ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] STM and random numbers
Hi, I'd like to be able to use randomIO, but I'm working within the context of STM. Is there a way to get these working together happily? For now, I guess I could kludgingly use unsafePerformIO inside STM (it's the other way around that's not allowed, right?), but I would need to be sure it doesn't get inlined. Thanks, Chad ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Resending: MissingH: profiler support?
On 1/12/07, Gregory Wright [EMAIL PROTECTED] wrote: Hi John, On Jan 11, 2007, at 8:06 PM, John Goerzen wrote: On 2007-01-11, Chris Eidhof [EMAIL PROTECTED] wrote: Hey, does anyone know about this? Resending as I got no replies (yet) ;) Just for the record, I have no idea; I've never really used profiling and couldn't figure out how to make it work in general (at least not in a short amount of time). Are you sure your problem is restricted to MissingH? I can't think of anything special about it that would throw off profiling. -- John Does MissingH's cabal file have a line Ghc-Prof-Options: -prof -auto-all ? The rhs of the option is added to compiler command line when the --enable-library-profiling option is included to configure. Without this, the --enable-library-profiling switch doesn't do anything. (Arguably a bug that cabal silently does nothing instead of reporting an error.) Cabal will build a profiling version of the library whether or not you have ghc-prof-options. Using '-auto-all' only adds more cost centres which you most likely don't want (unless you're working on the library itself). One might argue, however, that the convenience of having --enable-library-profiling on by default is worth the doubled build time. -- Cheers, Lemmih ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] STM and random numbers
On 1/12/07, Chad Scherrer [EMAIL PROTECTED] wrote: Hi, I'd like to be able to use randomIO, but I'm working within the context of STM. Is there a way to get these working together happily? For now, I guess I could kludgingly use unsafePerformIO inside STM (it's the other way around that's not allowed, right?), but I would need to be sure it doesn't get inlined. You could use GHC.Conc.unsafeIOToSTM. Just be aware that your transaction may be re-executed an arbitrary number of times. -- Cheers, Lemmih ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: STM and random numbers
Chad Scherrer schrieb: Hi, I'd like to be able to use randomIO, but I'm working within the context of STM. Is there a way to get these working together happily? How about adding an Int parameter for the inital seed and using setStdGen? C. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: STM and random numbers
Christian Maeder schrieb: Chad Scherrer schrieb: Hi, I'd like to be able to use randomIO, but I'm working within the context of STM. Is there a way to get these working together happily? How about adding an Int parameter for the inital seed and using setStdGen? is should be mkStdGen ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] STM and random numbers
On Jan 12, 2007, at 10:58 AM, Chad Scherrer wrote: Hi, I'd like to be able to use randomIO, but I'm working within the context of STM. Is there a way to get these working together happily? For now, I guess I could kludgingly use unsafePerformIO inside STM (it's the other way around that's not allowed, right?), but I would need to be sure it doesn't get inlined. Humm... I'd actually suggest you stop trying to break the rules, and use the portion of the random interface that doesn't require IO. You can pretty easily wrap a StdGen using StateT, and write your stuff in the monad (StateT StdGen STM). Or, (and I'm amazed this hasn't been done before), you can create a custom random monad that wraps up this behavior. Prototype attached. Now you can write in (RandT StdGen STM), and use the convenient getRandom method. Invoke like: dostuff :: IO () dostuff = do gen - newStdGen x - atomically (evalRandT stuff gen) process x stuff :: RandT StdGen STM Int stuff = do r - getRandom lift (someSTMaction r) Thanks, Chad Rob Dockins Speak softly and drive a Sherman tank. Laugh hard; it's a long way to the bank. -- TMBG Random.hs Description: Binary data ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] STM and random numbers
On Fri, 12 Jan 2007, Robert Dockins wrote: Humm... I'd actually suggest you stop trying to break the rules, and use the portion of the random interface that doesn't require IO. You can pretty easily wrap a StdGen using StateT, and write your stuff in the monad (StateT StdGen STM). Or, (and I'm amazed this hasn't been done before), you can create a custom random monad that wraps up this behavior. http://haskell.org/haskellwiki/New_monads/MonadRandom ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: MissingH: profiler support?
On 2007-01-12, Chris Eidhof [EMAIL PROTECTED] wrote: Thanks, this works! I had to build all the other libraries that are required with profiling support too. I also wrote it down on the MissingH wiki, see http://software.complete.org/missingh/wiki/Profiling Thanks for documenting that on the wiki -- I think you are the first contributor to it. -- John ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] STM and random numbers
Wow, lots of great ideas. Thanks, guys. Lemmih, I worry about the uncertainty in the semantics that seems to be introduced by the unsafe stuff. But I actually hadn't noticed GHC.Conc.unsafeIOToSTM before, so it's good to know it's there. Rich, Even if I use randomIO outside the STM code, I don't know of a (safe) way to bring it in. Anyway, the number of random values needed depends on other stuff going on within the STM part. Christian, I think setStdGen has the same problem as just using randomIO and ignoring the initial seed - there's no nice way of moving the (IO a) value generated into the STM monad. Rob, Henning, I think I'll take this approach, or something similar. Thanks for the pointers. -Chad ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] different performance of equivalent expression
Hello! I've run into strange effect that I can not explain. I have simple expression that can be written by two equivalent ways. However one way give much performance gain over another. Here is an example: -- apply function many times (tail-recursive) many n f x = if n == 0 then x else many (n-1) f $! (f x) -- first adder function adder1 = let r = many 500 sin 1.0 in \x - x + r -- second adder function adder2 = \x - x + many 500 sin 1.0 main = do putStrLn $ show $ adder1 1 putStrLn $ show $ adder1 2 putStrLn $ show $ adder1 3 putStrLn $ show $ adder1 4 putStrLn $ show $ adder2 1 putStrLn $ show $ adder2 2 putStrLn $ show $ adder2 3 putStrLn $ show $ adder2 4 If you run program it think some seconds performing math, and them prints 4 results immediately. But with adder2 function, it perform calculation in every call, which can be seen visually. It seems that compiler is able to cache in some way long computation in first case, but not in second. I always thought that let a = b in x + a is just a syntactic sugar for x + b. Is it wrong? Of course, this is just a toy example. In reality I was writing run-time compilation. Suppose, you have an simple arithmetic expression with variables. data Expr = Var String | Add Expr Expr | Mul Expr Expr | ... type Env = Map.Map String Double compile :: Expr - (Env - Double) compile e = case e of Var n - \env - env Map.! n Add e1 e2 - \env - (compile e1) env + (compile e2) env Mul e1 e2 - \env - (compile e1) env * (compile e2) env The same thing occur here. Expressions (compile e1) and (compile e2) are re-evaluated every time when compiled expression is run with some environment. So, it is much more an interpretation than compilation. I want that compile function returns expression that are pre-evaluated as much as possible to maximally speed up subsequent evaluation in different environments. How can I force (compile e1) to be evaluated eagerly in case line for Add/Mul? P.S. I'm using GHC 6.6 on Debian Linux (x86 arch). With best regards, Alexander. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] mapTuple
Is there anything in particular you're trying to accomplish? It seems like this is the type of thing you'd accomplish with typeclasses if you had a less general problem than you've presented. For example, mapShowTuple :: (Show a, Show b) = (a, b) - (String, String) mapShowTuple (x, y) = (show x, show y) That said, it would be nice do be able to do something a little more general, but still with a specific typeclass, like mapNumOpTuple :: (Num a, Num b) = (Num c = c - c) - (a, b) - (a, b) mapNumOpTuple f (x, y) = (f x, f y) (This unfortunately fails to typecheck; GHC chokes with Illegal polymorphic or qualified type. On the other hand, I'm still pretty new to Haskell myself, so maybe someone else knows how to write this correctly without doing complex type hackery.) It would also be nice to be able to generalize over all typeclasses, e.g. (pseudo-code here) mapTypeclassOpTuple :: for all typeclasses C ((C a, C b) = (C c = c - c) - (a, b) - (a, b)) but I don't even know how that would fit into Haskell's syntax. I suspect it's an idea that's been discussed, and I just don't know the term for it. Anyway, if you can make your problem more specific, it might be easier to solve. --Grady On 1/11/07, Marco Túlio Gontijo e Silva [EMAIL PROTECTED] wrote: Hello, is there a way to defined something as a map to use in tuples? I tried this: mapTuple f (a, b) = (f a, f b) But the type inferred to it is not as generic as I wanted: mapTuple :: (t - t1) - (t, t) - (t1, t1) Then I tried a different, but not much, implementation: mapTuple' f g (a, b) = (f a, g b) mapTuple f = mapTuple' f f But the inferred type was the same. Is there a way to define a function in which I can be able to do something as this? mapTuple show (string, True) -- malebria Marco Túlio Gontijo e Silva Correio (MSN): [EMAIL PROTECTED] Jabber (GTalk): [EMAIL PROTECTED] Telefone: 33346720 Celular: 98116720 Endereço: Rua Paula Cândido, 257/201 Gutierrez 30430-260 Belo Horizonte/MG Brasil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] different performance of equivalent expression
I've run into strange effect that I can not explain. I have simple expression that can be written by two equivalent ways. However one way give much performance gain over another. Here is an example: -- apply function many times (tail-recursive) many n f x = if n == 0 then x else many (n-1) f $! (f x) -- first adder function adder1 = let r = many 500 sin 1.0 in \x - x + r -- second adder function adder2 = \x - x + many 500 sin 1.0 main = do putStrLn $ show $ adder1 1 putStrLn $ show $ adder1 2 putStrLn $ show $ adder1 3 putStrLn $ show $ adder1 4 putStrLn $ show $ adder2 1 putStrLn $ show $ adder2 2 putStrLn $ show $ adder2 3 putStrLn $ show $ adder2 4 If you run program it think some seconds performing math, and them prints 4 results immediately. But with adder2 function, it perform calculation in every call, which can be seen visually. It seems that compiler is able to cache in some way long computation in first case, but not in second. Haskell implementations are allowed, but not required, to make use of referential transparency to substitute expressions for their results (and vice versa). The way I understand your example, it is entirely implementation dependent whether the result of many 500 sin 1.0 is reused from one application to the next. Certainly, with GHC it does depend on the amount of optimisation applied. With -O, GHC spits out all 8 results at once. I agree that Haskell, and laziness in particular, does require you to have some appreciation for the way the implementation performs. I can only guess that in the unoptimised case, it's easy for GHC to see the common subexpression in adder1, because you've given it a name, but it's not looking hard enough to find it in adder2. With optimisation, it's smart enough to resuse the result across both functions. So my advice here would be: always try the optimiser before you worry too much about strange performance! I always thought that let a = b in x + a is just a syntactic sugar for x + b. Is it wrong? In general, let expressions are more than simple syntactic sugar. Let expressions introduce lexical scope, allow mutually recursive bindings, and use irrefutable (lazy) pattern matching. See the report, section 3.12 for the details. The part that is probably most surprising to the unaware is that let bindings always use lazy pattern matching. The Gentle Introduction, section 4.4, explains lazy pattern matching better than I can: http://www.haskell.org/tutorial/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] mapTuple
On 12/01/07, Grady Lemoine [EMAIL PROTECTED] wrote: Is there anything in particular you're trying to accomplish? It seems like this is the type of thing you'd accomplish with typeclasses if you had a less general problem than you've presented. For example, mapShowTuple :: (Show a, Show b) = (a, b) - (String, String) mapShowTuple (x, y) = (show x, show y) That said, it would be nice do be able to do something a little more general, but still with a specific typeclass, like mapNumOpTuple :: (Num a, Num b) = (Num c = c - c) - (a, b) - (a, b) mapNumOpTuple f (x, y) = (f x, f y) (This unfortunately fails to typecheck; GHC chokes with Illegal polymorphic or qualified type. On the other hand, I'm still pretty new to Haskell myself, so maybe someone else knows how to write this correctly without doing complex type hackery.) It's close: {-# OPTIONS_GHC -fglasgow-exts #-} mapNumOpPair :: (Num a, Num b) = (forall c. Num c = c - c) - (a, b) - (a,b) mapNumOpPair f (x,y) = (f x, f y) It would also be nice to be able to generalize over all typeclasses, e.g. (pseudo-code here) mapTypeclassOpTuple :: for all typeclasses C ((C a, C b) = (C c = c - c) - (a, b) - (a, b)) but I don't even know how that would fit into Haskell's syntax. I suspect it's an idea that's been discussed, and I just don't know the term for it. That's an interesting idea, typeclass variables. It would require a bit of a kind system for typeclasses, but that's not so hard. I somehow doubt it would get used all *that* much though. Can anyone think of a clever way to apply this? - Cale ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] STM and random numbers
Rather than having a separate thread computing the random numbers using IO, why not just stick an StdGen in a TVar and write a function like: type RandomVar = TVar StdGen rnd :: RandomVar - STM a rnd var = do g - readTVar var let (r,g') = random g writeTVar var g' return r The user of this approach should be aware that it may lead to non-determinism. That is, the sequence of psuedo-random numbers extracted by any one thread will depend on those extracted by other threads, which may in turn depend on the scheduling of those threads. While non-determinism might be ideal for some applications of psuedo-random numbers, there are other applications (simulation, in particular) where it is useful to be able to reproduce an exact sequence of psuedo-random events by just reapplying the same initial seed. To do that, you would need (among other things) to thread a separate pseudo-random generator through each thread (using the approach described by Robert and Henning), and split the psuedo-random generator whenever forking a new thread. The TVar approach might also lead to excessive STM transaction abort-retry cycles, if multiple threads are retrieving many pseudo-random numbers via a single TVar. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe