From dons at cse.unsw.edu.au Mon Jan 1 02:46:29 2007 From: dons at cse.unsw.edu.au (Donald Bruce Stewart) Date: Mon Jan 1 02:43:08 2007 Subject: [Haskell-cafe] some way to reverse engineer lambda expressions out of the debugger? In-Reply-To: <8096545.post@talk.nabble.com> References: <8096545.post@talk.nabble.com> Message-ID: <20070101074629.GA31562@cse.unsw.EDU.AU> tphyahoo: > > I am a newbie learning haskell. (First forum post.) > > I am wondering if there is a trick to get debugging information about > functions out of the environment (which for me, for now, is ghci). > > In this example, > > *UnixTools> :t map (*) [1,2] > map (*) [1,2] :: (Num a) => [a -> a] > > This is very nice, but I would *really* like to see something like > > *UnixTools> explodeLambda( map (*) [1,2] ) > [(\x -> 1*x),(\x -> 2*x)] > > Yes, maybe I'm dreaming, but I would like haskell to reverse engineer / > pretty print lambda expressions for me. You can use 'hat' to trace/reduce expressions. http://www.cs.york.ac.uk/fp/hat/ The new ghci debugger can print closures too, but I'm not sure if it does what you want. All very possible, maybe a little experimental though. -- Don From gale at sefer.org Mon Jan 1 06:02:13 2007 From: gale at sefer.org (Yitzchak Gale) Date: Mon Jan 1 05:58:46 2007 Subject: [Haskell-cafe] Composing functions with runST Message-ID: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> Can anyone explain the following behavior (GHCi 6.6): Prelude Control.Monad.ST> runST (return 42) 42 Prelude Control.Monad.ST> (runST . return) 42 :1:9: Couldn't match expected type `forall s. ST s a' against inferred type `m a1' In the second argument of `(.)', namely `return' In the expression: (runST . return) 42 In the definition of `it': it = (runST . return) 42 Thanks, Yitz From brianh at metamilk.com Mon Jan 1 06:35:18 2007 From: brianh at metamilk.com (Brian Hulley) Date: Mon Jan 1 06:31:47 2007 Subject: [Haskell-cafe] Composing functions with runST References: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> Message-ID: <036401c72d98$ea36d750$96c82950@osmet> Yitzchak Gale wrote: > Can anyone explain the following behavior (GHCi 6.6): > > Prelude Control.Monad.ST> runST (return 42) > 42 > Prelude Control.Monad.ST> (runST . return) 42 > > :1:9: > Couldn't match expected type `forall s. ST s a' > against inferred type `m a1' > In the second argument of `(.)', namely `return' > In the expression: (runST . return) 42 > In the definition of `it': it = (runST . return) 42 Section 7.4.8 of GHC manual states that a type variable can't be instantiated with a forall type, though it doesn't give any explanation why. Hazarding a guess, I suggest it *might* be due to the fact that forall s. ST s a means forall s. (ST s a) whereas you'd need it to mean (forall s. ST s) a in order for it to unify with (m a). Just a guess - I'd be interested to know the real reason as well. Brian. -- http://www.metamilk.com From allbery at ece.cmu.edu Mon Jan 1 06:35:46 2007 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Mon Jan 1 06:32:22 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> References: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> Message-ID: <17469D44-5D7D-4CF3-A8EF-88BD0295D60F@ece.cmu.edu> On Jan 1, 2007, at 6:02 , Yitzchak Gale wrote: > Prelude Control.Monad.ST> (runST . return) 42 > > :1:9: > Couldn't match expected type `forall s. ST s a' > against inferred type `m a1' I think the problem is that technically runST is a data constructor (possibly not relevant) which takes a function as a parameter (definitely relevant). In the normal compositional model, (f . g) x = f (g x), you're conceptually invoking f on the result of g x (g is independent of f); here, you're lifting the function g x into the ST s a monad via f (g is dependent on f). -- brandon s. allbery [linux,solaris,freebsd,perl] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH From gale at sefer.org Mon Jan 1 07:48:03 2007 From: gale at sefer.org (Yitzchak Gale) Date: Mon Jan 1 07:44:36 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <036401c72d98$ea36d750$96c82950@osmet> References: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> <036401c72d98$ea36d750$96c82950@osmet> Message-ID: <2608b8a80701010448s69db1f87r40d765271868ff7e@mail.gmail.com> I wrote: >> Prelude Control.Monad.ST> runST (return 42) >> 42 >> Prelude Control.Monad.ST> (runST . return) 42 >> >> :1:9: >> Couldn't match expected type `forall s. ST s a' >> against inferred type `m a1' Brian Hulley wrote: > Hazarding a guess, I suggest it *might* be due to the fact that > > forall s. ST s a > > means > > forall s. (ST s a) > > whereas you'd need it to mean > > (forall s. ST s) a > > in order for it to unify with (m a). But then why does "return 42" type successfully as forall s. (ST s a)? It needs that same unification. -Yitz From bulat.ziganshin at gmail.com Mon Jan 1 05:38:23 2007 From: bulat.ziganshin at gmail.com (Bulat Ziganshin) Date: Mon Jan 1 07:49:05 2007 Subject: [Haskell-cafe] Strange type behavior in GHCi 6.4.2 In-Reply-To: <4683d9370612310847l6e3b3b1dtb75c3c1004211521@mail.gmail.com> References: <5bbe25930612020953g76990381q5984f6fb9c0bb091@mail.gmail.com> <4683d9370612281214h2c61b1e3rdfbf1d52fbcd837@mail.gmail.com> <5bbe25930612282312n3ac92d98l8bfe4b5105a43252@mail.gmail.com> <884220918.20061229142910@gmail.com> <4683d9370612290730m1a403e78m57ada566d4a54c06@mail.gmail.com> <623292260.20061230164252@gmail.com> <553544725.20061231121247@gmail.com> <402502AC-E429-4213-9B32-8EEE0D2E63A7@augustsson.net> <1874462187.20061231170752@gmail.com> <4683d9370612310847l6e3b3b1dtb75c3c1004211521@mail.gmail.com> Message-ID: <986838042.20070101133823@gmail.com> Hello Kirsten, Sunday, December 31, 2006, 7:47:18 PM, you wrote: >> this don't say anything place. and these rules have their own source: it's >> hard to optimize using your path. but when program optimization is just >> adding a few options/pragmas to the program, it' becomes cheap enough to >> change these rules. didn't you thought about it? >> > In my experience, adding pragmas and toying with options without > insight into what they do is not "cheap", because it takes up the > programmer's time, and time is more important than anything else. using pragmas is much cheaper than profiling/reading low level code > Every minute spent typing in pragmas is a minute lost that could have it's a great loss :) > been spent thinking about how to write your code more elegantly, and > in my experience -- and again, maybe it's just that I'm slow -- adding > pragmas doesn't help. When it comes to inlining and specializing, GHC > tends to be smarter than I am. (Once more, maybe it's just that I'm > slow.) I'd rather focus my energies on doing the things GHC can't > (usually) do, like replacing an O(n^2) algorithm with an O(log n) > algorithm. in a minute? :) i don't agree with your arguments. if you want your program to become faster you should use various techniques. what i proposed is fastest one. i don't see meaning in opposing algorithm optimization to other techniques my own optimization experience was experimenting with variants of source code and once i understood which variants of code can't be inlined at all i just use inline pragma for all critical functions. i've learned how ghc generates STG code once and for all, and don't think that i need to see STG anymore -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com From bulat.ziganshin at gmail.com Mon Jan 1 05:55:56 2007 From: bulat.ziganshin at gmail.com (Bulat Ziganshin) Date: Mon Jan 1 07:49:13 2007 Subject: [Haskell-cafe] Strange type behavior in GHCi 6.4.2 In-Reply-To: <10642DDE-2D80-4396-B218-AD1F4F73765A@augustsson.net> References: <5bbe25930612020953g76990381q5984f6fb9c0bb091@mail.gmail.com> <4683d9370612281214h2c61b1e3rdfbf1d52fbcd837@mail.gmail.com> <5bbe25930612282312n3ac92d98l8bfe4b5105a43252@mail.gmail.com> <884220918.20061229142910@gmail.com> <4683d9370612290730m1a403e78m57ada566d4a54c06@mail.gmail.com> <623292260.20061230164252@gmail.com> <553544725.20061231121247@gmail.com> <402502AC-E429-4213-9B32-8EEE0D2E63A7@augustsson.net> <1874462187.20061231170752@gmail.com> <4683d9370612310847l6e3b3b1dtb75c3c1004211521@mail.gmail.com> <10642DDE-2D80-4396-B218-AD1F4F73765A@augustsson.net> Message-ID: <45929009.20070101135556@gmail.com> Hello Lennart, Sunday, December 31, 2006, 10:26:24 PM, you wrote: > I think you can be much more productive in optimizing your code > if you actually understand what's going on. I usually don't go as > far as looking at compiler intermediate code; I usually stick with > profiling (or look at assembly code if it's a really performance > critical inner loop). for GHC??? :) if we say about optimizing C programs, old days i usually looked into asm code and then darken and go to rewrote it in asm :) nowadays i look only at memory access patterns, it's enough, at least for a few programs i optimized this year for GHC, i usually know which functions need to become faster, so i personally don't need profiling. moreover, program should be optimized for wide variety of situations, while profiling run shows only one execution scenario. i don't think that looking into STG (don't even said about C--/asm) may help me to optimize program. which program-specific things i can find here, after i've once learned how generation of STG code works? > Then you can start optimizing. That can be > by changing algorithm, changing data representation, strictness > annotations, etc. yes, i don't use profiling because i use more specific instruments to investigate performance bottlenecks > It can also be by inserting some INLINE or SPECIALIZE > pragmas, but that's more rare (don't get me wrong about those pragmas, > I introduced them in Haskell with hbc). But I think just adding pragmas > willy-nilly is a bad idea; I find that most serious performance problems > cannot be solved by those means, instead you need a higher level > approach. i proposed it as fast approach to raise performance, as alternative to your suggestion to profile and read code, where you not said anything about changing algorithms :) -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com From bulat.ziganshin at gmail.com Mon Jan 1 06:01:02 2007 From: bulat.ziganshin at gmail.com (Bulat Ziganshin) Date: Mon Jan 1 07:49:21 2007 Subject: [Haskell-cafe] some way to reverse engineer lambda expressions out of the debugger? In-Reply-To: <8096545.post@talk.nabble.com> References: <8096545.post@talk.nabble.com> Message-ID: <654370282.20070101140102@gmail.com> Hello tphyahoo, Saturday, December 30, 2006, 11:53:53 AM, you wrote: > *UnixTools> explodeLambda( map (*) [1,2] ) >[(\x ->> 1*x),(\x -> 2*x)] i'm wondering whether it's possible to use typeclasses to implement this, like packages for symbolic computations (afair, it was demonstrated by Oleg) -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com From apfelmus at quantentunnel.de Mon Jan 1 07:55:04 2007 From: apfelmus at quantentunnel.de (apfelmus@quantentunnel.de) Date: Mon Jan 1 07:54:05 2007 Subject: [Haskell-cafe] Re: Possible (GHC or HGL) bug or ?? In-Reply-To: <45987763.4010709@protempore.net> References: <45987763.4010709@protempore.net> Message-ID: Calvin Smith wrote: > This basically works, in that it does exactly what I want in Hugs, but > GHC sometimes pauses partway through rendering, and does not continue > rendering until I type any key (except space, which exits) or > unfocus/refocus the window, or move the mouse pointer across the window. > > Sometimes, more often the first time in a GHCI session, it renders > completely with no pauses, and it seems to pause more and more if I > evaluate main, then close the window, evaluate again in the same GHCI > session, repeatedly. The same pausing behavior is observed in a > GHC-compiled executable. > > When the problem occurs, there is a message to the console that says: > "thread blocked indefinitely". I can reproduce this on OS X with ghc-6.4.2, X11-1.1 and HGL-3.1. The console message is rare but I also got it once. This looks like a bug in HGL, perhaps some issue with polling the event queue in a threaded fashion. > p.s. Any stylistic or other comments about the code welcome too. The infinite list of colors is a very good idea. It might also be a good idea not to mess with trigonometry when creating the snowflake. These things can be put into a single function (rotate) which rotates a point around the origin by a specified number of degrees. The following code demonstrates this. Note that the resulting snowflake has slightly different proportions than your original one, but it shouldn't be a problem to adjust this. module Main where import Graphics.SOE main = runGraphics $ do w <- openWindow "Snowflake Fractal" (600, 600) drawInWindow w $ snowflake (300,300) 200 (cycle $ enumFrom Blue) spaceClose w spaceClose w = do k <- getKey w if k == ' ' then closeWindow w else spaceClose w rotate :: Double -> Point -> Point rotate deg (x,y) = (truncate $ c*x' - s*y', truncate $ s*x' + c*y') where (x',y') = (fromIntegral x, fromIntegral y) rad = deg * pi / 180 (s,c) = (sin rad, cos rad) translate :: (Int, Int) -> Point -> Point translate (dx,dy) (x,y) = (x + dx, y + dy) minSize = 2 :: Int snowflake :: Point -> Int -> [Color] -> Graphic snowflake _ h _ | h <= minSize = emptyGraphic snowflake pos h (c:cs) = overGraphics $ map (\pos -> snowflake pos (h `div` 3) cs) (mkPoints corners) ++ map (withColor c . polygon . mkPoints) [triangle1, triangle2] where -- things gets specified by their angle -- with respect to the y-axis mkPoints = map $ translate pos . flip rotate (0,h) triangle1 = [0, 120, 240] triangle2 = map (180+) triangle1 corners = map (60*) [0..5] Also note that I eschewed (drawInWindow) in favor of (overGraphic), but I think that SOE will introduce that at some point, too. A minor hint is to use Double instead of Float. It doesn't really matter, but today's computers internally favor Double ("double precision floating point number"). Regards, apfelmus From gale at sefer.org Mon Jan 1 08:11:13 2007 From: gale at sefer.org (Yitzchak Gale) Date: Mon Jan 1 08:07:46 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <17469D44-5D7D-4CF3-A8EF-88BD0295D60F@ece.cmu.edu> References: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> <17469D44-5D7D-4CF3-A8EF-88BD0295D60F@ece.cmu.edu> Message-ID: <2608b8a80701010511j2c7db0a5lb6d5b1936dd7c981@mail.gmail.com> Brandon S. Allbery KF8NH wrote: > I think the problem is that technically runST is a data constructor > (possibly not relevant) No, at least not in GHC. It is a function. > which takes a function as a parameter (definitely relevant). It takes the type (forall s. ST s a) as its only parameter. How is that more or less a function than anything else? > In the normal compositional model, (f . g) x > = f (g x), you're conceptually invoking f on the result of g x (g is > independent of f); here, you're lifting the function g x into the ST > s a monad via f (g is dependent on f). I don't think I am using any special lifting mechanism here. The "return" function does exploit the fact that ST s has a Monad instance, but I only used the "return" function for simplicity. The same thing happens if you construct a function that explicitly returns (forall s. ST s a) and use that instead of "return": Prelude Control.Monad.ST> :set -fglasgow-exts Prelude Control.Monad.ST> let {f :: a -> (forall s. ST s a); f x = return x} Prelude Control.Monad.ST> runST (f 42) 42 Prelude Control.Monad.ST> (runST . f) 42 :1:9: Couldn't match expected type `forall s. ST s a' against inferred type `ST s a1' ... Here is another possible clue to what is happening. When I try to define that same function f using monomorphic syntax, it fails: Prelude Control.Monad.ST> let {f :: a -> (forall s. ST s a); f = return} :1:39: Inferred type is less polymorphic than expected Quantified type variable `s' escapes Expected type: a -> forall s1. ST s1 a Inferred type: a -> ST s a In the expression: return In the definition of `f': f = return (Of course, the MR is not relevant here, because I am providing an explicit type signature.) _ _ ... ... _ _ -Yitz From gale at sefer.org Mon Jan 1 08:30:35 2007 From: gale at sefer.org (Yitzchak Gale) Date: Mon Jan 1 08:27:08 2007 Subject: [Haskell-cafe] Re: Composing functions with runST In-Reply-To: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> References: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> Message-ID: <2608b8a80701010530i31e64124tc07e77790e4eba07@mail.gmail.com> The plot thickens... It seems that I can't even use STRefs. Something is really wrong here. Prelude Control.Monad.ST Data.STRef> runST $ do {r<-newSTRef 2; readSTRef r} :1:8: Couldn't match expected type `forall s. ST s a' against inferred type `a1 b' In the second argument of `($)', namely `do r <- newSTRef 2 readSTRef r' In the expression: runST $ (do r <- newSTRef 2 readSTRef r) In the definition of `it': it = runST $ (do r <- newSTRef 2 readSTRef r) From dmhouse at gmail.com Mon Jan 1 08:45:34 2007 From: dmhouse at gmail.com (David House) Date: Mon Jan 1 08:42:07 2007 Subject: [Haskell-cafe] Re: Composing functions with runST In-Reply-To: <2608b8a80701010530i31e64124tc07e77790e4eba07@mail.gmail.com> References: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> <2608b8a80701010530i31e64124tc07e77790e4eba07@mail.gmail.com> Message-ID: On 01/01/07, Yitzchak Gale wrote: > It seems that I can't even use STRefs. > Something is really wrong here. > > Prelude Control.Monad.ST Data.STRef> runST $ do {r<-newSTRef 2; readSTRef r} Again, this is due to section 7.4.8 [1] of the GHC user manual, which states that you can't instantiate a type variable with a type involving a forall. You're trying to unify the first parameter of ($) :: a -> b -> a with (forall s. ST s a -> a), which is illegal. Using parentheses works: runST (do r <- newSTRef 2; readSTRef r) However, I'm as much in the dark as you are as to _why_ this is illegal. [1]: http://haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#universal-quantification -- -David House, dmhouse@gmail.com From ctm at cs.nott.ac.uk Mon Jan 1 08:49:01 2007 From: ctm at cs.nott.ac.uk (Conor McBride) Date: Mon Jan 1 08:45:40 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> References: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> Message-ID: <4599114D.6020603@cs.nott.ac.uk> Hi Yitzchak Gale wrote: > Can anyone explain the following behavior (GHCi 6.6): I don't know if I can explain it entirely, or justify it properly, but I do have some idea what the issue is. Type inference with higher-ran types is weird. The primary reference is Practical type inference for arbitrary-rank types Simon Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, and Mark Shields. To appear in the Journal of Functional Programming. http://research.microsoft.com/~simonpj/papers/higher-rank/index.htm 'The paper is long, but is strongly tutorial in style.' Back in the Hindley-Milner days, we knew exactly what polymorphism could happen where. All the free type variables were existential (hence specialisable); generalisation over free type variables happened at let. Unification was untroubled by issues of scope or skolem constants. The machine could always guess what your idea was because you weren't allowed to have interesting ideas. Now you can ask for polymorphism in funny places by writing non-H-M types explicitly. As in runST :: (forall s. ST s a) -> a When you apply runST, you create a non-let source of (compulsory) polymorphism. You get a new type variable a and a new type constant s, and the argument is checked against (ST s a). Let's look. > Prelude Control.Monad.ST> runST (return 42) > 42 Can (return 42) have type ST s a, for all s and some a? Yes! Instantiate return's monad to (ST s) and a to the type of 42 (some Num thing? an Int default?). In made up System F, labelling specialisable unknowns with ? runST@?a (/\s. return@(ST s)@?a (42@?a)) such that Num ?a Now what's happening here? > Prelude Control.Monad.ST> (runST . return) 42 We're trying to type an application of (.) (.) :: (y -> z) -> (x -> y) -> (x -> z) We get two candidates for y, namely what runST wants (forall s. ST s a) and what return delivers (m b) and these must unify if the functions are to compose. Oops, they don't. The point, I guess, is that application in Haskell source code is no longer always translated exactly to application in System F. We don't just get (runST@?a) (return@?m@?b) such that (forall s. ST s ?a) = ?m ?b we get that extra /\s. inserted for us, thanks to the explicit request for it in the type of runST. The type of (.) makes no such request. Same goes for type of ($), so runST behaves differently from (runST $). It's a murky world. Happy New Year Conor From simonpj at microsoft.com Mon Jan 1 12:26:27 2007 From: simonpj at microsoft.com (Simon Peyton-Jones) Date: Mon Jan 1 12:22:55 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <4599114D.6020603@cs.nott.ac.uk> Message-ID: Conor and others are right; it's all to do with type inference. There is nothing wrong with the program you are writing, but it's hard to design a type inference algorithm that can figure out what you are doing. The culprit is that you want to instantiate a polymorphic function (here (.) or ($) in your examples) with a higer-rank polymorphic type (the type of runST, in this case). That requires impredicative polymorphism and while GHC now allows that, it only allows it when it's pretty obvious what is going on --- and sadly this case is not obvious enough. The system GHC uses is described in our paper http://research.microsoft.com/~simonpj/papers/boxy Simon | -----Original Message----- | From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of | Conor McBride | Sent: 01 January 2007 13:49 | To: haskell-cafe@haskell.org | Subject: Re: [Haskell-cafe] Composing functions with runST | | Hi | | Yitzchak Gale wrote: | > Can anyone explain the following behavior (GHCi 6.6): | | I don't know if I can explain it entirely, or justify it properly, but I | do have some idea what the issue is. Type inference with higher-ran | types is weird. The primary reference is | | Practical type inference for arbitrary-rank types | Simon Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, and Mark | Shields. | To appear in the Journal of Functional Programming. | | http://research.microsoft.com/~simonpj/papers/higher-rank/index.htm | | 'The paper is long, but is strongly tutorial in style.' | | Back in the Hindley-Milner days, we knew exactly what polymorphism could | happen where. All the free type variables were existential (hence | specialisable); generalisation over free type variables happened at let. | Unification was untroubled by issues of scope or skolem constants. The | machine could always guess what your idea was because you weren't | allowed to have interesting ideas. | | Now you can ask for polymorphism in funny places by writing non-H-M | types explicitly. As in | | runST :: (forall s. ST s a) -> a | | When you apply runST, you create a non-let source of (compulsory) | polymorphism. You get a new type variable a and a new type constant s, | and the argument is checked against (ST s a). Let's look. | | > Prelude Control.Monad.ST> runST (return 42) | > 42 | | Can (return 42) have type ST s a, for all s and some a? Yes! Instantiate | return's monad to (ST s) and a to the type of 42 (some Num thing? an Int | default?). In made up System F, labelling specialisable unknowns with ? | | runST@?a (/\s. return@(ST s)@?a (42@?a)) such that Num ?a | | Now what's happening here? | | > Prelude Control.Monad.ST> (runST . return) 42 | | We're trying to type an application of (.) | | (.) :: (y -> z) -> (x -> y) -> (x -> z) | | We get two candidates for y, namely what runST wants (forall s. ST s a) | and what return delivers (m b) and these must unify if the functions are | to compose. Oops, they don't. | | The point, I guess, is that application in Haskell source code is no | longer always translated exactly to application in System F. We don't | just get | | (runST@?a) (return@?m@?b) such that (forall s. ST s ?a) = ?m ?b | | we get that extra /\s. inserted for us, thanks to the explicit request | for it in the type of runST. The type of (.) makes no such request. Same | goes for type of ($), so runST behaves differently from (runST $). | | It's a murky world. | | Happy New Year | | Conor | | _______________________________________________ | Haskell-Cafe mailing list | Haskell-Cafe@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-cafe From paolo.veronelli at gmail.com Mon Jan 1 12:30:04 2007 From: paolo.veronelli at gmail.com (paolo.veronelli@gmail.com) Date: Mon Jan 1 12:27:08 2007 Subject: [Haskell-cafe] Arrays performance Message-ID: <20070101173004.GB1405@paolino.selfip.org> Good year everyone. I'm timing the following script.I'm not expert to evaluate th O'ness of this code, I hope someone can do it. The program clusters n integers in m buckets based on their distance. Anyway I thing should be linear.So I timed som executions changing the first arg. First argument n is the number of integers to be clustered.Their are choosen randomly between 0 and 100. Second argument m is the number of buckets.For them I choose a value choosen like before. In the timings second argument is always 10. Points Time (ms) 100 40 200 93 400 269 800 831 1600 3063 3200 12693 6400 54708 I'd like to know if the algorithm is the cause for this timings (it's not linear) or if I need to use other kinds of Arrays Thanks Paolino ---------------------------------------------------------------- import Data.Maybe import Data.List import Data.Array.Diff import System.Environment import Control.Monad.State import Control.Arrow import Random inc l i = l // [(i,l!i + 1)] switch l i = l // [(i,not (l!i))] constArray n v = listArray (0,n-1) (repeat v) data CState = CState {clusters :: [(Int,Int)],remi :: Int,colsHeap ::DiffArray Int Int ,rowsFlag :: DiffArray Int Bool} devil [] _ = return () devil (l@(row,col):ls) d = do s@(CState cs r hs fs) <- get let ns = s { clusters = (l:cs), rowsFlag = switch fs row, colsHeap = inc hs col } update | c < d = put ns | (c == d) && (r > 0) = put ns { remi = r - 1 } | otherwise = return () where c = hs ! col when (not (fs ! row)) update devil ls d comp f g x y = (f x) `g` (f y) swap = snd &&& fst collapse = (head &&& unzip) >>> (fst *** snd) mcluster :: [(Int,Int)] -> [(Int,[Int])] mcluster ls = let (lr,lc) = (f *** f) (unzip ls) where f = length.nub -- coo space width (k,r) = divMod lr lc CState cs _ _ _ = execState (devil ls k) CState{clusters = [],remi = r,colsHeap = constArray lc 0,rowsFlag = constArray lr False } in map collapse . groupBy (comp fst (==)) . sort . map swap $ cs coupage ls = zip [0..] ls delta fxy xs ys = [(abs(x-y),(n,m))|(n,x) <- coupage xs, (m,y) <- coupage ys] decoupage ls n = fromJust $ lookup n (coupage ls) test xs ys = let d = snd.unzip.sort $ delta (\x y -> abs (x -y)) xs ys in map (decoupage ys *** map (decoupage xs)) (mcluster d) -- call it with 2 args, the number ov values and the number of clusters -- 101 10 will cluster 101 values in 10 clusters main = do args <- getArgs gen <- getStdGen let [n,m] = map read args let (ps,bs) = splitAt n (take (m + n) (randomRs (0,100) gen)) print $ test ps bs From joelr1 at gmail.com Mon Jan 1 13:28:05 2007 From: joelr1 at gmail.com (Joel Reymont) Date: Mon Jan 1 13:24:40 2007 Subject: [Haskell-cafe] Glasgow Distributed Haskell Message-ID: <958C2B76-C249-4F58-B144-9426BB82D2BC@gmail.com> Is anyone using GdH? Can someone tell me why it's not part of the GHC distribution? It seems that GdH is not being developed anymore and I think it's a real pity! Thanks, Joel -- http://wagerlabs.com/ From gale at sefer.org Mon Jan 1 13:43:43 2007 From: gale at sefer.org (Yitzchak Gale) Date: Mon Jan 1 13:40:16 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: References: <4599114D.6020603@cs.nott.ac.uk> Message-ID: <2608b8a80701011043m2f8e3519mf443833876076245@mail.gmail.com> Simon Peyton-Jones wrote: > There is nothing wrong with the program you are writing, > but it's hard to design a type inference algorithm that can > figure out what you are doing. Thank you for your response. What I was actually trying to do was this: It seems to me that a natural notion of a state transformer in the ST monad is the type: STRef s st -> ST s a That is in some sense intermediate between pure monadic state transformers on the one hand, and doing state completely within the ST or IO monad with STRefs or IORefs. The idea is that you could then write converter functions like this: stToState :: MonadState st m => (STRef s st -> ST s a) -> m a That would make it very convenient, for example, to use arrays inside a pure state monad. The type signatures above do ensure (as far as I can see) that the opacity of the ST state thread is not violated. But unfortunately, the protective shield in runST created by the higher-rank polymorphism is too thick. Any ideas? A better approach? Thanks, Yitz From u.stenzel at web.de Mon Jan 1 14:16:22 2007 From: u.stenzel at web.de (Udo Stenzel) Date: Mon Jan 1 14:27:39 2007 Subject: [Haskell-cafe] Arrays performance In-Reply-To: <20070101173004.GB1405@paolino.selfip.org> References: <20070101173004.GB1405@paolino.selfip.org> Message-ID: <20070101191621.GA1488@web.de> paolo.veronelli@gmail.com wrote: > I'm timing the following script.I'm not expert to evaluate th O'ness > of this code, I hope someone can do it. The program clusters n > integers in m buckets based on their distance. Anyway I thing should > be linear.So I timed som executions changing the first arg. > [...] > mcluster :: [(Int,Int)] -> [(Int,[Int])] > mcluster ls = let > (lr,lc) = (f *** f) (unzip ls) where f = length.nub -- coo space width > (k,r) = divMod lr lc > CState cs _ _ _ = execState (devil ls k) > CState{clusters = [],remi = r,colsHeap = constArray lc 0,rowsFlag = constArray lr False } > in map collapse . groupBy (comp fst (==)) . sort . map swap $ cs > > coupage ls = zip [0..] ls > delta fxy xs ys = [(abs(x-y),(n,m))|(n,x) <- coupage xs, (m,y) <- coupage ys] > decoupage ls n = fromJust $ lookup n (coupage ls) > > test xs ys = > let d = snd.unzip.sort $ delta (\x y -> abs (x -y)) xs ys > in > map (decoupage ys *** map (decoupage xs)) (mcluster d) It isn't, but not for the reasons you might suspect. You're using 'nub', which is quadratic, and your 'coupage' is also quadratic because it uses 'lookup' on a list, which is linear, a linear number of times. You can get this down to O(n * log n) if you replace these lists by Data.Map and Data.Set, to get down to O(n) you need arrays there, too, but that would be pointless, because you're also using 'sort', which is already in O(n * log n). The core of the algorithm is clearly linear in the length of its input. (Btw, putting 'devil' into a state monad doesn't make much sense. I think, ordinary recursion would be more clear. In fact, it's a 'foldl'.) -Udo -- You're damned if you do; you're damned if you don't. -- Bart Simpson -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070101/64183de0/attachment.bin From anatoly.zaretsky at gmail.com Mon Jan 1 15:06:13 2007 From: anatoly.zaretsky at gmail.com (Anatoly Zaretsky) Date: Mon Jan 1 15:02:45 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <2608b8a80701011043m2f8e3519mf443833876076245@mail.gmail.com> References: <4599114D.6020603@cs.nott.ac.uk> <2608b8a80701011043m2f8e3519mf443833876076245@mail.gmail.com> Message-ID: On 1/1/07, Yitzchak Gale wrote: > > stToState :: MonadState st m => (STRef s st -> ST s a) -> m a > > That would make it very convenient, for example, to > use arrays inside a pure state monad. > > The type signatures above do ensure (as far as I can see) > that the opacity of the ST state thread is not violated. But > unfortunately, the protective shield in runST created by the > higher-rank polymorphism is too thick. Probably, stToState :: MonadState st m => (forall s. STRef s st -> ST s a) -> m a E.g. stToState :: MonadState st m => (forall s. STRef s st -> ST s a) -> m a stToState f = do s <- get let (x, s') = runST (do r <- newSTRef s x <- f r s' <- readSTRef r return (x, s')) put s' return x -- Best regerds, Tolik From u.stenzel at web.de Mon Jan 1 15:32:46 2007 From: u.stenzel at web.de (Udo Stenzel) Date: Mon Jan 1 16:27:40 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <2608b8a80701011043m2f8e3519mf443833876076245@mail.gmail.com> References: <4599114D.6020603@cs.nott.ac.uk> <2608b8a80701011043m2f8e3519mf443833876076245@mail.gmail.com> Message-ID: <20070101203246.GB1488@web.de> Yitzchak Gale wrote: > It seems to me that a natural notion of a state transformer > in the ST monad is the type: > > STRef s st -> ST s a Are there any useful functions of this type? I guess, your intention is that this "transformer" makes no other use of the ST monad than reading or writing a single variable. It seems, every such function better had a purely functional interface anyway, even if it makes use of runST internally. > stToState :: MonadState st m => (STRef s st -> ST s a) -> m a > > The type signatures above do ensure (as far as I can see) > that the opacity of the ST state thread is not violated. I doubt that. The "transformer" you pass in could have captured references from a different state thread, which is exactly the problem the rank-2 type should prevent. I guess, the type signature you want is stToState :: MonadState st m => (forall s . STRef s st -> ST s a) -> m a which should actually work with runST and which would also be a bit pointless (see above). At least if I got rank-2 types correctly, which isn't guaranteed. > Any ideas? A better approach? Uhm... use MonadState in the first place? The converse is comparatively easily accomplished: stateToST :: STRef s st -> State st a -> ST s a stateToST ref action = do (a, st') <- readSTRef ref >>= runState action writeSTRef ref st' return a -Udo -- "Human legalese is the schema language of our society." -- Tim Berners-Lee in http://w3.org/DesignIssues/Evolution -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070101/fd4ba31e/attachment.bin From igloo at earth.li Mon Jan 1 17:53:02 2007 From: igloo at earth.li (Ian Lynagh) Date: Mon Jan 1 17:49:34 2007 Subject: [Haskell-cafe] porting ghc In-Reply-To: <20061231143933.GA31066@matrix.chaos.earth.li> References: <5b3fa8f0612182207r53e5e551s4c72f7f7fa7f6a38@mail.gmail.com> <20061231143933.GA31066@matrix.chaos.earth.li> Message-ID: <20070101225302.GA16454@matrix.chaos.earth.li> On Sun, Dec 31, 2006 at 02:39:33PM +0000, Ian Lynagh wrote: > > > http://haskell.org/ghc/docs/6.6/html/building/sec-porting-ghc.html I've been reminded that the building guide is being moved to the wiki, so http://hackage.haskell.org/trac/ghc/wiki/Building (in particular http://hackage.haskell.org/trac/ghc/wiki/Building/Porting) is probably the best to work from. Thanks Ian From huschi at gmx.org Mon Jan 1 18:08:11 2007 From: huschi at gmx.org (Martin Huschenbett) Date: Mon Jan 1 18:11:40 2007 Subject: [Haskell-cafe] Generating Source Code with Haskell Message-ID: Hi, my aim is to transform an XML file into C++ source code with a Haskell program. The part that parses the XML is already finished (using HaXML) but the part that generates the C++ code is still remaining. Is there already any work on this topic? Maybe even on generating Java or any other object oriented or imperative language. My first approach was to simply generate the C++ code as text using a pretty printing library but this becomes ugly very fast. Next I thought about generating and rendering the AST of the resulting C++ code. But I don't want to reinvent the wheel. Regards, Martin. From gale at sefer.org Mon Jan 1 19:30:12 2007 From: gale at sefer.org (Yitzchak Gale) Date: Mon Jan 1 19:26:43 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <20070101203246.GB1488@web.de> References: <4599114D.6020603@cs.nott.ac.uk> <2608b8a80701011043m2f8e3519mf443833876076245@mail.gmail.com> <20070101203246.GB1488@web.de> Message-ID: <2608b8a80701011630h1db56cbag9ae608d374ba8c80@mail.gmail.com> I wrote: >> It seems to me that a natural notion of a state transformer >> in the ST monad is the type: >> STRef s st -> ST s a Udo Stenzel wrote: > Are there any useful functions of this type? Sure. Anything that can be written as a pure state transformer can be written this way, of course. In addition, you can use mutable arrays for speed. Here is a concrete example: Let's say you want to shuffle a large list randomly, within a larger application that lives inside some MTL monad stack. Among other things, your monad m satisfies (RandomGen g, MonadState g m), perhaps after a lift. Well, it turns out that using Data.Sequence or Data.IntMap to shuffle a list becomes prohibitive if you might have more than about 10^5 elements in your list. So in that case you will need to use a mutable array, and you now need ST. Combining ST and MTL can be messy, even in this simple case. You will probably write something with a type like RandomGen g => [a] -> g -> ST s ([a], g) apply runST (tiptoeing carefully around the paradoxes mentioned in this thread), and then build an MTL state thing out of it. Wouldn't it be nice if instead you could just write: shuffle :: (RandomGen g, MonadState g m) => [a] -> m [a] shuffle = stToState . shuffleST > I guess, your intention is that this "transformer" makes > no other use of the ST monad than reading > or writing a single variable. Well, it can do whatever it wants inside, but it needs to expose any state that is shared externally. If that state is complex, you can use the same techniques that you would use for a State monad - either build the complexity into the state type using, say, records, or compose several transformers. In this case composition would be: STRef s st1 -> STRef s st2 -> ST s a > It seems, every such function better have > a purely functional interface anyway, Yes, that is the intended use. > even if it makes use of runST internally. You would not need to, stToState would take care of runST. >> stToState :: MonadState st m => (STRef s st -> ST s a) -> m a >> The type signatures above do ensure (as far as I can see) >> that the opacity of the ST state thread is not violated. > I doubt that. The "transformer" you pass in could have captured > references from a different state thread, which is exactly the problem > the rank-2 type should prevent. Hmm, you're right. > I guess, the type signature you want is > stToState :: MonadState st m => (forall s . STRef s st -> ST s a) -> m a Or use some opaque type or monad and do something unsafe inside. > > Any ideas? A better approach? > Uhm... use MonadState in the first place? You mean use ST in the first place. Yes, but I want to avoid that. > The converse is comparatively > easily accomplished... Yes. Regards, Yitz From dons at cse.unsw.edu.au Mon Jan 1 22:22:23 2007 From: dons at cse.unsw.edu.au (Donald Bruce Stewart) Date: Mon Jan 1 22:18:57 2007 Subject: [Haskell-cafe] Haskell Weekly News: January 02, 2007 Message-ID: <20070102032223.GB12350@cse.unsw.EDU.AU> --------------------------------------------------------------------------- Haskell Weekly News http://sequence.complete.org/hwn/20070102 Issue 55 - January 02, 2007 --------------------------------------------------------------------------- Welcome to issue 55 of HWN, a weekly newsletter covering developments in the Haskell community. This week brings a new release of vty and HsColour, and some interesting discussion over the holiday break. Announcements hscolour-1.6. Malcolm Wallace [1]announced HsColour, a popular syntax-highlighter for Haskell code. It can generate ANSI terminal colour codes, HTML, and CSS, and can insert hyperlink anchors for function definitions (useful in conjunction with [2]Haddock). [3]HsColour-1.6 is now available. The major addition is a new LaTeX output mode. 1. http://article.gmane.org/gmane.comp.lang.haskell.general/14677 2. http://haskell.org/haddock 3. http://www.cs.york.ac.uk/fp/darcs/hscolour Dimensional: Statically checked physical dimensions. Björn Buckwalter [4]announced version 0.1 of [5]Dimensional, a module for statically checked physical dimensions. The module facilitates calculations with physical quantities while statically preventing e.g. addition of quantities with differing physical dimensions. 4. http://article.gmane.org/gmane.comp.lang.haskell.general/14691 5. http://code.google.com/p/dimensional/ vty 2.0. Stefan O'Rear [6]announced a new major version of [7]vty. Differences from 1.0 include: vty now uses a record type for attributes, instead of bitfields in an Int; vty now supports setting background colors; you can now explicitly specify 'default' colors; vty now supports Unicode characters on output, automatically setting and resetting UTF-8 mode. 6. http://article.gmane.org/gmane.comp.lang.haskell.general/14703 7. http://members.cox.net/stefanor/vty 'Lambda Revolution' tshirts. Paul Johnson [8]announced the creation of a new Haskell tshirt, on the theme of 'The Lambda Revolution'. Tshirts are available from [9]CafePress, and the designs are freely available. 8. http://article.gmane.org/gmane.comp.lang.haskell.cafe/17916 9. http://www.cafepress.com/l_revolution Discussion Beautiful concurrency. Simon Peyton-Jones [10]mentioned that he's been writing a chapter on concurrency and transactional memory for a new book, 'Beautiful code'. [11]A first draft is available and Simon welcomes constructive suggestions for improvement. The book is aimed at a general audience of programmers, not Haskell geeks, so tries to explain everything necessary. If you are not a Haskell expert, your input would be particularly valuable. 10. http://article.gmane.org/gmane.comp.lang.haskell.general/14681 11. http://haskell.org/haskellwiki/Talk:SantaClausProblem Limits to implicit parallelism in functional applications. John DeTreville [12]announced a short paper about how much implicit parallelism there might be in ordinary functional applications. 12. http://article.gmane.org/gmane.comp.lang.haskell.general/14699 Inlining higher order functions. Norman Ramsey [13]asked about fine grained control for inlining in higher order functions. 13. http://article.gmane.org/gmane.comp.lang.haskell.glasgow.user/11467 Red-black trees as a nested datatype. Jim Apple [14]described how to implement red-black trees as a nested datatype. 14. http://article.gmane.org/gmane.comp.lang.haskell.cafe/17957 SYB for XML: deserialization and collections. Alexander Jacobson [15]asked about approaches to simplifying boilerplate in HAppS associated with XML serialization and state deserialization. 15. http://article.gmane.org/gmane.comp.lang.haskell.cafe/17922 Flattening a lisp-style tree. pphetra [16]asked about flattening heterogeneous lists (or trees) in Haskell. 16. http://thread.gmane.org/gmane.comp.lang.haskell.cafe/17976/focus=17976 Jobs Functional programming at Jane Street Capital. Yaron Minsky [17]announced that [18]Jane Street Capital is again looking to hire some top-notch functional programmers. Of particular note is that Jane Street Europe Ltd. now has an office in London, and we are particularly interested in hiring someone for that office with strong systems administration skills in addition to experience with functional programming languages. The ideal candidate has: a commitment to the practical, experience with functional programming languages (such as Haskell). Applicants should also have experience with UNIX and a deep understanding of computers and technology and a strong mathematical background. 17. http://article.gmane.org/gmane.comp.lang.haskell.general/14683 18. http://www.janestcapital.com/tech.html Blog noise [19]Haskell news from the blogosphere. * [20]Secret Santas in Haskell III: Lather, Rinse, Repeat 1 * [21]More Haskell in Java 7 or 8? * [22]Generalized vs. dynamic interfaces * [23]Type classes in Java * [24]Static vs dynamic typing: do what thou wilt * [25]Hoogle 4 progress * [26]Hoogle Progress, HsMan features * [27]The York Haskell Compiler: 1000 patches! * [28]Evaluating cellular automata is co-monadic * [29]Tying Knots Generically * [30]Rails -> Ruby -> Haskell * [31]A Sermon on Programming Languages * [32]Thoughtful revision control * [33]readFile' * [34]Code unraveller * [35]The Haskell Meta Tutorial * [36]Monads * [37]My Haskell Experience * [38]Communities * [39]Darcs: The source code management system of the future? * [40]On strong type systems * [41]On Programming Languages and Productivity 19. http://planet.haskell.org/ 20. http://mult.ifario.us/articles/2006/12/22/secret-santas-in-haskell-iii-collect-reap-repeat 21. http://blogs.msdn.com/ralflammel/archive/2006/12/21/more-haskell-in-java-7-or-8.aspx 22. http://blogs.msdn.com/ralflammel/archive/2006/12/23/generalized-vs-dynamic-interfaces.aspx 23. http://syntaxfree.wordpress.com/2006/12/23/et-tu-brute/ 24. http://syntaxfree.wordpress.com/2006/12/24/static-vs-dynamic-typing-do-what-thou-wilt/ 25. http://neilmitchell.blogspot.com/2006/12/hoogle-4-progress.html 26. http://neilmitchell.blogspot.com/2006/12/hoogle-progress-hsman-features.html 27. http://yhc06.blogspot.com/2006/12/1000-patches.html 28. http://sigfpe.blogspot.com/2006/12/evaluating-cellular-automata-is.html 29. http://sigfpe.blogspot.com/2006/12/tying-knots-generically.html 30. http://rubynations.wordpress.com/2006/12/28/evolutionrails-ruby-haskell/ 31. http://www.dailyspeculations.com/wordpress/?p=101 32. http://koweycode.blogspot.com/2006/12/distributed-chiming-in.html 33. http://koweynlg.blogspot.com/2006/12/meh.html 34. http://koweycode.blogspot.com/2006/12/unraveller.html 35. http://koweycode.blogspot.com/2006/12/haskell-metatutorial.html 36. http://hierodule.livejournal.com/69052.html 37. http://kawagner.blogspot.com/2006/12/my-haskell-experience.html 38. http://gravityboy.livejournal.com/31930.html 39. http://www.iovene.com/content/view/93/1/ 40. http://blog.tmorris.net/strong-type-systems/ 41. http://www.neilmix.com/2007/01/01/on-programming-languages-and-productivity/ Quotes of the Week * chessguy: [in regards to #haskell] man, it's amazing the difference between what happens when someone asks for help here, and what happens when they ask for help in another language channel * cjeris: It's amazing what some languages do to make thinking impossible, seemingly justified by the assumption that no one thinks anyway, so it's more important to make non-thinking programming as easy as possible. * edwinb: I've just walked past a poster advertising a gig by a band called 'The Awkward Squad'. I assume this means they provide output, play concurrently, and people take exception to them. * kfish: Apparently @pl also doubles as the command for producing an unintelligible flip-stream * Binkley: [Monads as clothes] using unsafePerformIO is kind of like going naked in public, might be safe in some contexts, but you really don't want to know what happens if you do it in a really bad one * quazimodo: I know why you guys are so ready to deal with me and put up with noob questions ... you program so fast compared to other language users that you have time to mess around? * iulus: IO, IO, it's off to bind we go ... * dons: all your imperative are belong to us * Logan Capaldo: I like constructing things with type errors. It lets me read the error and try and figure out what I'm really trying to do * glguy: In true Haskell form, after I realized what I was actually doing... all my functions melted down to about 2 lines each * jcreigh: I've found learning Haskell makes me feel vastly inferior to Haskell coders. ('Oh,', they say, 'That's just a fold over the hyper-monad fluxbox list. Here's the one-line replacement for your entire program.') * Saizan: [New Year's Fun] Yesterday I was so drunk I was trying to typecheck the people at the party... 'What's your monad!?' Code Watch Wed Dec 27 17:03:48 PST 2006. Manuel M T Chakravarty. [42]Parse and desugar equational constraints. With -findexed-types, equational constraints can appear in contexts wherever class predicates are allowed. The two argument types need to be boxed and rank 0. 42. http://article.gmane.org/gmane.comp.lang.haskell.cvs.ghc/18551 About the Haskell Weekly News Each week, new editions are posted to [43]the Haskell mailing list as well as to [44]the Haskell Sequence and [45]Planet Haskell. [46]RSS is also available, and headlines appear on [47]haskell.org. Headlines are available as [48]PDF. The Haskell Weekly News is also [49]available in Spanish translation. To help create new editions of this newsletter, please see the [50]contributing information. Send stories to dons at cse.unsw.edu.au. The darcs repository is available at darcs get [51]http://www.cse.unsw.edu.au/~dons/code/hwn 43. http://www.haskell.org/mailman/listinfo/haskell 44. http://sequence.complete.org/ 45. http://planet.haskell.org/ 46. http://sequence.complete.org/node/feed 47. http://haskell.org/ 48. http://www.cse.unsw.edu.au/~dons/code/hwn/archives/20070102.pdf 49. http://haskell.org/haskellwiki/HWN/es 50. http://haskell.org/haskellwiki/HWN 51. http://www.cse.unsw.edu.au/~dons/code/hwn From simonpj at microsoft.com Tue Jan 2 03:33:37 2007 From: simonpj at microsoft.com (Simon Peyton-Jones) Date: Tue Jan 2 03:30:09 2007 Subject: [Haskell-cafe] Glasgow Distributed Haskell In-Reply-To: <958C2B76-C249-4F58-B144-9426BB82D2BC@gmail.com> References: <958C2B76-C249-4F58-B144-9426BB82D2BC@gmail.com> Message-ID: GdH is maintained and distributed by Phil Trinder and his colleagues at Heriot Watt. I think it's still alive, but it's based on a much earlier version of GHC. If it's parallelism you're after, GHC (as distributed) runs on shared-memory multi-processors. But we don't have anything like GdH or GpH, which work on distributed-memory machines, yet. Simon | -----Original Message----- | From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe- | bounces@haskell.org] On Behalf Of Joel Reymont | Sent: 01 January 2007 18:28 | To: Haskell Cafe | Subject: [Haskell-cafe] Glasgow Distributed Haskell | | Is anyone using GdH? | | Can someone tell me why it's not part of the GHC distribution? | | It seems that GdH is not being developed anymore and I think it's a | real pity! | | Thanks, Joel | | -- | http://wagerlabs.com/ | | | | | | _______________________________________________ | Haskell-Cafe mailing list | Haskell-Cafe@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-cafe From gale at sefer.org Tue Jan 2 05:25:40 2007 From: gale at sefer.org (Yitzchak Gale) Date: Tue Jan 2 05:22:10 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <9a0b86ed0701020118p423b3be7nab5fa51956357809@mail.gmail.com> References: <2608b8a80701010302va1b0baeydc2bea4187c4b720@mail.gmail.com> <9a0b86ed0701020118p423b3be7nab5fa51956357809@mail.gmail.com> Message-ID: <2608b8a80701020225r59b59dafse44cd489628aa587@mail.gmail.com> Hi Thomas, You wrote: > How do I "import" Control.Monad.ST so I can experiment with it from > ghci and just do > runST > like you had. Instead of qualifying it in some way. In GHCi, use the :module command (:m) for built-in modules, and :load and :add for source files. In Hugs, use :load and :also for both. You need to run Hugs with the -98 flag to use Control.Monad.ST. > how do I do runST as fully qualified? Like this: Prelude> Control.Monad.ST.runST (do {r <- Data.STRef.newSTRef 2007; Data.STRef.readSTRef r}) 2007 Have fun with monads! Regards, Yitz From bulat.ziganshin at gmail.com Mon Jan 1 20:48:55 2007 From: bulat.ziganshin at gmail.com (Bulat Ziganshin) Date: Tue Jan 2 07:09:47 2007 Subject: [Haskell-cafe] Glasgow Distributed Haskell In-Reply-To: <958C2B76-C249-4F58-B144-9426BB82D2BC@gmail.com> References: <958C2B76-C249-4F58-B144-9426BB82D2BC@gmail.com> Message-ID: <983520712.20070102044855@gmail.com> Hello Joel, Monday, January 1, 2007, 9:28:05 PM, you wrote: > Is anyone using GdH? > Can someone tell me why it's not part of the GHC distribution? > It seems that GdH is not being developed anymore and I think it's a > real pity! ghc sources are open, so anyone can build his own GHC extension. GHC team can't support all these extended GHC versions btw, may be the following can help you: http://www.inf.ufes.br/~ffranzosi/BSPHlib-0.1.tar.gz -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com From joelr1 at gmail.com Tue Jan 2 08:08:33 2007 From: joelr1 at gmail.com (Joel Reymont) Date: Tue Jan 2 08:05:06 2007 Subject: [Haskell-cafe] Glasgow Distributed Haskell In-Reply-To: References: <958C2B76-C249-4F58-B144-9426BB82D2BC@gmail.com> Message-ID: <5B701702-C7E1-4B7B-B2E1-9CFD471CBE6D@gmail.com> On Jan 2, 2007, at 8:33 AM, Simon Peyton-Jones wrote: > GdH is maintained and distributed by Phil Trinder and his > colleagues at Heriot Watt. I think it's still alive, but it's > based on a much earlier version of GHC. I wonder how much work would it be to integrate it. Also, their servers are down for some reason, I can't open http:// www.macs.hw.ac.uk/~dsg/gdh/. > If it's parallelism you're after, GHC (as distributed) runs on > shared-memory multi-processors. But we don't have anything like > GdH or GpH, which work on distributed-memory machines, yet. I'm after Erlang in Haskell, if you will, for fault-tolerance and scalability. Thanks, Joel -- http://wagerlabs.com/ From joelr1 at gmail.com Tue Jan 2 08:09:06 2007 From: joelr1 at gmail.com (Joel Reymont) Date: Tue Jan 2 08:05:36 2007 Subject: [Haskell-cafe] Glasgow Distributed Haskell In-Reply-To: <983520712.20070102044855@gmail.com> References: <958C2B76-C249-4F58-B144-9426BB82D2BC@gmail.com> <983520712.20070102044855@gmail.com> Message-ID: <11ED0FF0-4590-4D1F-9674-3F076179CA67@gmail.com> On Jan 2, 2007, at 1:48 AM, Bulat Ziganshin wrote: > btw, may be the following can help you: > http://www.inf.ufes.br/~ffranzosi/BSPHlib-0.1.tar.gz Thanks Bulat. I don't know what this is, though, and the link is broken. -- http://wagerlabs.com/ From magr at cs.tu-berlin.de Tue Jan 2 09:00:03 2007 From: magr at cs.tu-berlin.de (Martin Grabmueller) Date: Tue Jan 2 08:56:41 2007 Subject: [Haskell-cafe] Announce: Package rdtsc for reading IA-32 time stamp counters Message-ID: <459A6563.80102@cs.tu-berlin.de> Hallo all, version 1.0 of package rdtsc has just been released. This small package contains one module called 'Rdtsc.Rdtsc'. This module provides the function 'rdtsc' for accessing the 'rdtsc' machine register on modern IA-32 processors. This is a 64-bit counter which counts the number of processor cycles since the machine has been powered up. Using this instruction, you can make very precise time measurements which are independent of the actual CPU frequency. But note that you can get strange results sometimes on a superscalar processor. A small program using this library looks like this: module Main where import Rdtsc.Rdtsc main = do t1 <- rdtsc t2 <- rdtsc putStrLn ("Cost of rdtsc (ffi call): " ++ show (t2 - t1)) Note that the Haskell foreign function interface imposes some additional overheads. On my machine, it takes about 950 cycles to call this function twice and to compute the difference, whereas in C the overhead is only about 84 cycles. The documentation for the package is available here: http://uebb.cs.tu-berlin.de/~magr/projects/rdtsc/ Download the source using darcs: darcs get http://uebb.cs.tu-berlin.de/~magr/darcs/rdtsc/ I would really like to get feedback on this little package, which already has been quite useful for me. Have fun and Happy Haskell Hacking in th New Year, Martin From gale at sefer.org Tue Jan 2 09:54:11 2007 From: gale at sefer.org (Yitzchak Gale) Date: Tue Jan 2 09:50:40 2007 Subject: [Haskell-cafe] Announce: Package rdtsc for reading IA-32 time stamp counters In-Reply-To: <459A6563.80102@cs.tu-berlin.de> References: <459A6563.80102@cs.tu-berlin.de> Message-ID: <2608b8a80701020654g69f96324sff180b215d6347d9@mail.gmail.com> On 1/2/07, Martin Grabmueller wrote: > version 1.0 of package rdtsc has just been released. > This small package contains one module called 'Rdtsc.Rdtsc'. > This module provides the function 'rdtsc' for accessing > the 'rdtsc' machine register on modern IA-32 processors. Very nice! I have a few comments: 1. What happens when someone tries this on a platform other than IA-32? I would hope for some predictable exception to be thrown (hopefully not a segfault). Hmm, checking System.Info.arch would probably cost a few cycles. I wonder how much difference that would make. Or maybe there is a CPP macro that could hide this function completely on non-IA-32? 2. Shouldn't this module be called System.Rtdsc? Or maybe even System.CPUTime.Rdtsc (even though to a systems person this is a very different animal, something feels right about that to me. I think that is where most people would look for it first.). > ...note that you can get strange results > sometimes on a superscalar processor. There are a number of serious problems with using RDTSC, so anyone using it should first read up about it. In particular: using it on a very old machine could prevent Linux from booting; using it on recent high-end machines can be very inaccurate (as Martin pointed out). Microsoft "strongly discourages" its use on Windows. That said, in practice many people find RDTSC very useful. Source: http://en.wikipedia.org/wiki/RDTSC Thanks for posting this module. Regards, Yitz From haskell at list.mightyreason.com Tue Jan 2 15:20:19 2007 From: haskell at list.mightyreason.com (Chris Kuklewicz) Date: Tue Jan 2 15:16:45 2007 Subject: [Haskell-cafe] Socket Programming In-Reply-To: References: Message-ID: <459ABE83.3090600@list.mightyreason.com> Mark Goldman wrote: > I am trying to write a toy echo server that can handle multiple > connections. I would like to be able to test and see if there are any > connections waiting to be accepted on a socket. In C and related > languages I would use something like select or poll to be nice to the > OS, what would I use with the current haskell libs given that I can't > seem to find a function to test if accept would block or not? > > -mdg > The wiki page http://haskell.org/haskellwiki/Concurrency_demos/Graceful_exit uses accepting connections as its example. The main idea is use accept (which blocks) in a background thread and which provides the resulting connections to some inter-thread data stream: MVar, MChan, TMVar, TChan, or your own structure. Shutting down a system is usually subtle, and that wiki page concentrates on a trying to create a solution which provides dependable shutdown semantics. From conal at conal.net Tue Jan 2 16:36:14 2007 From: conal at conal.net (Conal Elliott) Date: Tue Jan 2 16:32:43 2007 Subject: [Haskell-cafe] mtl vs monads In-Reply-To: References: Message-ID: Are the mtl and monads (monadLib) packages both in active use? Is one being phased out? - Conal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070102/24eeb132/attachment.htm From bringert at cs.chalmers.se Tue Jan 2 16:41:18 2007 From: bringert at cs.chalmers.se (Bjorn Bringert) Date: Tue Jan 2 16:37:48 2007 Subject: [Haskell-cafe] Generating Source Code with Haskell In-Reply-To: References: Message-ID: <82E4167E-0B5C-4237-9EDF-CA0CBF6A6661@cs.chalmers.se> On Jan 2, 2007, at 0:08 , Martin Huschenbett wrote: > Hi, > > my aim is to transform an XML file into C++ source code with a > Haskell program. The part that parses the XML is already finished > (using HaXML) but the part that generates the C++ code is still > remaining. Is there already any work on this topic? Maybe even on > generating Java or any other object oriented or imperative language. > > My first approach was to simply generate the C++ code as text using > a pretty printing library but this becomes ugly very fast. Next I > thought about generating and rendering the AST of the resulting C++ > code. But I don't want to reinvent the wheel. When I want to generate source code, I often write a grammar for the language fragment that I need and use BNFC (http://www.cs.chalmers.se/ ~markus/BNFC/) to make a pretty-printer. If you want nicely indented output, you sometimes have to tweak the generated pretty-printer a bit. /Bjorn From hjgtuyl at chello.nl Tue Jan 2 17:33:42 2007 From: hjgtuyl at chello.nl (Henk-Jan van Tuyl) Date: Tue Jan 2 17:30:11 2007 Subject: [Haskell-cafe] Re: [Haskell] Haskell Weekly News: January 02, 2007 In-Reply-To: <20070102032223.GB12350@cse.unsw.EDU.AU> References: <20070102032223.GB12350@cse.unsw.EDU.AU> Message-ID: On Tue, 02 Jan 2007 04:22:23 +0100, Donald Bruce Stewart wrote: > * edwinb: I've just walked past a poster advertising a gig by a band > called 'The Awkward Squad'. I assume this means they provide > output, play concurrently, and people take exception to them. Is there a tutorial on how to tackle this band? -- Met vriendelijke groet, Henk-Jan van Tuyl -- http://Van.Tuyl.eu/ -- Using Opera's revolutionary e-mail client: https://secure.bmtmicro.com/opera/buy-opera.html?AID=789433 From m at ryangunter.com Tue Jan 2 20:25:30 2007 From: m at ryangunter.com (Mike Gunter) Date: Tue Jan 2 20:22:21 2007 Subject: [Haskell-cafe] Extensible static checking of dimensions? In-Reply-To: <8b2a1a960612281231ke56bfc9vd002d220dbd6f49@mail.gmail.com> ( =?iso-8859-1?q?Bj=F6rn_Buckwalter's_message_of?= "Thu, 28 Dec 2006 15:31:28 -0500") References: <8b2a1a960612280630x39722e50h8f2f75820d954a32@mail.gmail.com> <8b2a1a960612281231ke56bfc9vd002d220dbd6f49@mail.gmail.com> Message-ID: <87tzz89a0l.fsf_-_@c966553-A.attbi.com> The very nice Buckwalter and Denney dimensional-numbers packages both work on a fixed set of base dimensions. This is a significant restriction for me--I want to avoid adding apples to oranges as well as avoiding adding meters to grams. Is it possible to have an extensible set of base dimensions? If so, how usable can such a system be made? Is it very much worse than a system with a fixed set of base dimensions? thanks, -m From dons at cse.unsw.edu.au Wed Jan 3 02:06:27 2007 From: dons at cse.unsw.edu.au (Donald Bruce Stewart) Date: Wed Jan 3 02:03:06 2007 Subject: [Haskell-cafe] Announce: Package rdtsc for reading IA-32 time stamp counters In-Reply-To: <459A6563.80102@cs.tu-berlin.de> References: <459A6563.80102@cs.tu-berlin.de> Message-ID: <20070103070627.GB32372@cse.unsw.EDU.AU> magr: > Hallo all, > > version 1.0 of package rdtsc has just been released. > Very nice. I've attached some small patches: a) to move the src into System.CPUTime.Rdtsc (more intuitive space) b) move C src into cbits dir (standard name) Good work, Don -------------- next part -------------- New patches: [update cabal file Don Stewart **20070103070147] { hunk ./rdtsc.cabal 1 -Name: rdtsc -Version: 1.0 -License: GPL -License-file: COPYING -Author: Martin Grabmueller -Maintainer: magr@cs.tu-berlin.de -Homepage: http://uebb.cs.tu-berlin.de/~magr/projects/rdtsc/ -Category: Timing, Profiling -Synopsis: Binding for the rdtsc machine instruction -Description: This module provides the function 'rdtsc' for accessing +Name: rdtsc +Version: 1.0 +License: GPL +License-file: COPYING +Author: Martin Grabmueller +Maintainer: magr@cs.tu-berlin.de +Homepage: http://uebb.cs.tu-berlin.de/~magr/projects/rdtsc/ +Category: Timing, Profiling +Synopsis: Binding for the rdtsc machine instruction +Description: This module provides the function 'rdtsc' for accessing hunk ./rdtsc.cabal 22 -Stability: Experimental -Build-depends: base -Exposed-Modules: Rdtsc.Rdtsc -Extensions: ForeignFunctionInterface -C-sources: Rdtsc/rdtsc.c -Include-dirs: Rdtsc -Install-includes: rdtsc.h +Stability: Experimental +Build-depends: base +Exposed-Modules: System.CPUTime.Rdtsc +Extensions: ForeignFunctionInterface +C-sources: cbits/rdtsc.c +Include-dirs: cbits +Install-includes: rdtsc.h +ghc-options: -O -Wall -Werror } [Move C code into standard cbits/ dir, and .hs code under System.CPUTime Don Stewart **20070103070159] { adddir ./System adddir ./System/CPUTime move ./Rdtsc/Rdtsc.hs ./System/CPUTime/Rdtsc.hs adddir ./cbits move ./Rdtsc/rdtsc.c ./cbits/rdtsc.c move ./Rdtsc/rdtsc.h ./cbits/rdtsc.h rmdir ./Rdtsc hunk ./System/CPUTime/Rdtsc.hs 3 --- Module: Rdtsc.Rdtsc +-- Module: System.CPUTime.Rdtsc hunk ./System/CPUTime/Rdtsc.hs 27 -module Rdtsc.Rdtsc(rdtsc) where +module System.CPUTime.Rdtsc(rdtsc) where } [And update tests Don Stewart **20070103070333] { hunk ./tests/Makefile 2 -GHCFLAGS=-fglasgow-exts -i../.. +GHCFLAGS=-O -fglasgow-exts -i../.. hunk ./tests/Makefile 13 - $(CC) $(CFLAGS) -o $@ -I../Rdtsc test_rdtsc.c rdtsc.o + $(CC) $(CFLAGS) -o $@ -I../cbits test_rdtsc.c rdtsc.o hunk ./tests/Makefile 15 -rdtsc.o: ../Rdtsc/rdtsc.c ../Rdtsc/rdtsc.h - $(CC) $(CFLAGS) -c -I../Rdtsc $< +rdtsc.o: ../cbits/rdtsc.c ../cbits/rdtsc.h + $(CC) $(CFLAGS) -c -I../cbits $< hunk ./tests/TestRdtsc.hs 3 -import Rdtsc.Rdtsc +import System.CPUTime.Rdtsc } Context: [TAG rdtsc 1.0 Martin Grabmueller **20070102134714] Patch bundle hash: d553b3c78207e6bb4968f3eee8eb94641875c768 From u.stenzel at web.de Wed Jan 3 08:03:20 2007 From: u.stenzel at web.de (Udo Stenzel) Date: Wed Jan 3 08:28:31 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <2608b8a80701011630h1db56cbag9ae608d374ba8c80@mail.gmail.com> References: <4599114D.6020603@cs.nott.ac.uk> <2608b8a80701011043m2f8e3519mf443833876076245@mail.gmail.com> <20070101203246.GB1488@web.de> <2608b8a80701011630h1db56cbag9ae608d374ba8c80@mail.gmail.com> Message-ID: <20070103130320.GA1542@web.de> Yitzchak Gale wrote: > Here is a concrete example: > > Let's say you want to shuffle a large list randomly, > within a larger application that lives inside some > MTL monad stack. Among other things, your monad > m satisfies (RandomGen g, MonadState g m), perhaps > after a lift. > > Well, it turns out that using Data.Sequence or Data.IntMap > to shuffle a list becomes prohibitive if you might have > more than about 10^5 elements in your list. So in that > case you will need to use a mutable array, and you now > need ST. > > Combining ST and MTL can be messy, even in this simple > case. You will probably write something with a type like > > RandomGen g => [a] -> g -> ST s ([a], g) But why would you even want to do this? It's ugly and cumbersome. You'd plug a runST in there and get shuffle :: RandomGen g => [a] -> g -> ([a], g) or lift it into a state monad. Telling the world that you messed with imperative code inside is completely pointless, since the only thing you could possibly do with the result anyway is apply runST to it. > Wouldn't it be nice if instead you could just write: > > shuffle :: (RandomGen g, MonadState g m) => [a] -> m [a] > shuffle = stToState . shuffleST It seems, what you really want is shuffleST :: RandomGen g => [a] -> StateT g ST [a] No need to stick the generator into a mutable variable. Maybe you even want a MonadST class, analogous to MonadIO. > >Uhm... use MonadState in the first place? > > You mean use ST in the first place. No, I don't. -Udo -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070103/2050bdf2/attachment.bin From sethg at ropine.com Wed Jan 3 09:31:38 2007 From: sethg at ropine.com (Seth Gordon) Date: Wed Jan 3 09:28:07 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: References: Message-ID: <459BBE4A.20902@ropine.com> Simon Peyton-Jones wrote: > Conor and others are right; it's all to do with type inference. There is nothing wrong with the program you are writing, but it's hard to design a type inference algorithm that can figure out what you are doing. > > The culprit is that you want to instantiate a polymorphic function (here (.) or ($) in your examples) with a higer-rank polymorphic type (the type of runST, in this case). That requires impredicative polymorphism and while GHC now allows that, it only allows it when it's pretty obvious what is going on --- and sadly this case is not obvious enough. I don't know enough type theory to suggest a specific patch, but I hope a future version of GHC can do the right thing for (.) and ($) in this situation (and possibly for other functions that simply rearrange their arguments, like flip). >From a friendliness-to-newbies point of view, these error messages are a tremendous wart. I've been on haskell-cafe for a little over three months and seen postings from three people who were tripped up by this (the first of them was myself). So I can't just tell someone who's just starting to learn Haskell that "f $ g y" is equivalent to "f (g y)"; I have to say "those two are *almost always* equivalent, but if you use $ and the compiler complains about not being able to match the expected and the inferred type and a type signature in the error message has the word 'forall', try rewriting that expression without the $ and see if it compiles". Eeeww. From cs-haskell at protempore.net Wed Jan 3 11:02:08 2007 From: cs-haskell at protempore.net (Calvin Smith) Date: Wed Jan 3 10:58:34 2007 Subject: [Haskell-cafe] Re: Possible (GHC or HGL) bug or ?? In-Reply-To: References: <45987763.4010709@protempore.net> Message-ID: <459BD380.2050106@protempore.net> apfelmus@quantentunnel.de wrote: > Calvin Smith wrote: >> >> When the problem occurs, there is a message to the console that says: >> "thread blocked indefinitely". > > I can reproduce this on OS X with ghc-6.4.2, X11-1.1 and HGL-3.1. The > console message is rare but I also got it once. This looks like a bug in > HGL, perhaps some issue with polling the event queue in a threaded fashion. > Thanks very much for checking this on a different platform and GHC. I filed a bug report with the HGL maintainer. >> p.s. Any stylistic or other comments about the code welcome too. > > It might also be a good idea not to mess with trigonometry when creating > the snowflake. Yes, that is much cleaner. > The following code demonstrates this. Your solution is very elegant, and a big improvement over my messy first solution. Thanks for the very instructive code! Regards, Calvin From dmhouse at gmail.com Wed Jan 3 11:46:17 2007 From: dmhouse at gmail.com (David House) Date: Wed Jan 3 11:42:43 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <459BBE4A.20902@ropine.com> References: <459BBE4A.20902@ropine.com> Message-ID: On 03/01/07, Seth Gordon wrote: > So I can't just tell someone who's just starting to learn Haskell that > "f $ g y" is equivalent to "f (g y)"; I have to say "those two are > *almost always* equivalent, but if you use $ and the compiler complains > about not being able to match the expected and the inferred type and a > type signature in the error message has the word 'forall', try rewriting > that expression without the $ and see if it compiles". Eeeww. Why would someone just starting to learn Haskell be using ST? The canonical tutorial structure is to start with the pure stuff and only introduce the (more complicated!) impure stuff (ST, IORefs, etc.) in an 'advanced techniques' or similar section. -- -David House, dmhouse@gmail.com From joelr1 at gmail.com Wed Jan 3 11:54:18 2007 From: joelr1 at gmail.com (Joel Reymont) Date: Wed Jan 3 11:50:45 2007 Subject: [Haskell-cafe] darcs repo for yampa + gadt Message-ID: Folks, I have a version of Yampa with Henrik Nilsson's GADT optimizations that I cleaned up for ghc 6.6 and cabalized. Would it be possible to set it up at darcs.haskell.org and if so how should I go about it? Thanks, Joel -- http://wagerlabs.com/ From sethg at ropine.com Wed Jan 3 12:15:00 2007 From: sethg at ropine.com (Seth Gordon) Date: Wed Jan 3 12:11:28 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: References: <459BBE4A.20902@ropine.com> Message-ID: <459BE494.9040603@ropine.com> David House wrote: > >> So I can't just tell someone who's just starting to learn Haskell that >> "f $ g y" is equivalent to "f (g y)"; I have to say "those two are >> *almost always* equivalent, but if you use $ and the compiler complains >> about not being able to match the expected and the inferred type and a >> type signature in the error message has the word 'forall', try rewriting >> that expression without the $ and see if it compiles". Eeeww. > > Why would someone just starting to learn Haskell be using ST? The > canonical tutorial structure is to start with the pure stuff and only > introduce the (more complicated!) impure stuff (ST, IORefs, etc.) in > an 'advanced techniques' or similar section. I (and one other person on this list) ran into this issue when I was trying to use takusen to make Haskell talk to a RDBMS. You obviously need to learn advanced techniques to *implement* such a thing, but you shouldn't need advanced knowledge to *use a library* that happens to use higher-rank polymorphic types in its API. There are many routes to fluency in a language, and not everybody is suitable for the route of "here are the axioms underlying the language and the simplest code that applies them; after you thoroughly understand those, we'll show you how to make something practical". Some of us prefer the route of "here are some examples of how to get practical things done; after you're comfortable with them, we'll show you the theory that underlies them". Actually, I suspect that *most* of us prefer the second route. Set theory is closer to the theoretical foundations of mathematics than arithmetic, but when elementary schools tried teaching kids set theory, it didn't work out so well. From paul at cogito.org.uk Wed Jan 3 13:27:13 2007 From: paul at cogito.org.uk (Paul Johnson) Date: Wed Jan 3 13:23:42 2007 Subject: [Haskell-cafe] Glasgow Distributed Haskell Message-ID: <459BF581.3040702@cogito.org.uk> Joel Reymont wrote: > I'm after Erlang in Haskell, if you will, for fault-tolerance and > scalability. I think the way to do Erlang in Haskell is to build a middleware layer on top of the language, not try to make the language into something it is not. In this kind of environment you need to be able to upgrade components while the system is running. The careful Haskell habit of separating stateful operations from pure functions is useful here. I gather that the HAppS project is working along similar lines, and for similar reasons. Take a look at it. http://happs.org/HAppS/README.html Paul. From sebastian.sylvan at gmail.com Wed Jan 3 13:31:36 2007 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Wed Jan 3 13:28:03 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: References: <459BBE4A.20902@ropine.com> Message-ID: <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> On 1/3/07, David House wrote: > On 03/01/07, Seth Gordon wrote: > > So I can't just tell someone who's just starting to learn Haskell that > > "f $ g y" is equivalent to "f (g y)"; I have to say "those two are > > *almost always* equivalent, but if you use $ and the compiler complains > > about not being able to match the expected and the inferred type and a > > type signature in the error message has the word 'forall', try rewriting > > that expression without the $ and see if it compiles". Eeeww. > > Why would someone just starting to learn Haskell be using ST? The > canonical tutorial structure is to start with the pure stuff and only > introduce the (more complicated!) impure stuff (ST, IORefs, etc.) in > an 'advanced techniques' or similar section. > (slightly OT) It's true that this is the typical way of learning Haskell, but I for one think it's a bad way of learning Haskell. Very few real world programs get by without the "impure" stuff, so if you give the newbie the impression that it isn't there (by postponing it) there's a chance he'll run into a situation where he needs it before it's been even mentioned (queue newbie going "bah, academic language" and switching to C++). I find that the Haskell introductions I like the most are the ones that accompany papers about STM and such. I.e. ones which have to teach the reader about the basics of Haskell IO, but doesn't have enough space to start with the pretty stuff. Mix that with some actual comutations to show off some pretty stuff and you'll have a newbie who is both excited about the cool looking features of the pure aspects of Haskell, but completely aware of the fact that you can do impure stuff as well. Oh yeah, I agree that the relationship between ($) and (.) is a bit ugly from the user's perspective. It may have very good reasons, but I'd prefer consistency towards the user (i.e. spot when someone is using ($) with higher ranked types and do rewriting) rather than consistency towards the compiler. -- Sebastian Sylvan +46(0)736-818655 UIN: 44640862 From paolo.veronelli at gmail.com Wed Jan 3 13:38:20 2007 From: paolo.veronelli at gmail.com (Paolo Veronelli) Date: Wed Jan 3 13:35:17 2007 Subject: [Haskell-cafe] Arrays performance In-Reply-To: <20070101191621.GA1488@web.de> References: <20070101173004.GB1405@paolino.selfip.org> <20070101191621.GA1488@web.de> Message-ID: <20070103183820.GA1487@paolino.selfip.org> Quoting Udo Stenzel : > paolo.veronelli@gmail.com wrote: > > It isn't, but not for the reasons you might suspect. You're using > 'nub', which is quadratic, and your 'coupage' is also quadratic because > it uses 'lookup' on a list, which is linear, a linear number of times. > You can get this down to O(n * log n) if you replace these lists by > Data.Map and Data.Set, to get down to O(n) you need arrays there, too, > but that would be pointless, because you're also using 'sort', which is > already in O(n * log n). The core of the algorithm is clearly linear in > the length of its input. > > (Btw, putting 'devil' into a state monad doesn't make much sense. I > think, ordinary recursion would be more clear. In fact, it's a > 'foldl'.) Ok, I've simplified some code and moved to foldl, to collect the result. I paste new version in case you care give me some moe suggestion. Thanks. Paolino From rfh at reillyhayes.com Wed Jan 3 14:00:56 2007 From: rfh at reillyhayes.com (Reilly Hayes) Date: Wed Jan 3 13:57:23 2007 Subject: [Haskell-cafe] Socket Programming In-Reply-To: <459ABE83.3090600@list.mightyreason.com> References: <459ABE83.3090600@list.mightyreason.com> Message-ID: Or you could ignore the problem of shutdown altogether: http://swig.stanford.edu/~candea/papers/crashonly/ On Jan 2, 2007, at 12:20 PM, Chris Kuklewicz wrote: > Mark Goldman wrote: >> I am trying to write a toy echo server that can handle multiple >> connections. I would like to be able to test and see if there are >> any >> connections waiting to be accepted on a socket. In C and related >> languages I would use something like select or poll to be nice to the >> OS, what would I use with the current haskell libs given that I can't >> seem to find a function to test if accept would block or not? >> >> -mdg >> > > The wiki page http://haskell.org/haskellwiki/Concurrency_demos/ > Graceful_exit > uses accepting connections as its example. > > The main idea is use accept (which blocks) in a background thread > and which > provides the resulting connections to some inter-thread data > stream: MVar, > MChan, TMVar, TChan, or your own structure. > > Shutting down a system is usually subtle, and that wiki page > concentrates on a > trying to create a solution which provides dependable shutdown > semantics. > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe From cmb21 at kent.ac.uk Wed Jan 3 14:29:31 2007 From: cmb21 at kent.ac.uk (C.M.Brown) Date: Wed Jan 3 14:26:01 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> References: <459BBE4A.20902@ropine.com> <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> Message-ID: Hi, > It's true that this is the typical way of learning Haskell, but I for > one think it's a bad way of learning Haskell. > Very few real world programs get by without the "impure" stuff, so if > you give the newbie the impression that it isn't there (by postponing > it) there's a chance he'll run into a situation where he needs it > before it's been even mentioned (queue newbie going "bah, academic > language" and switching to C++). I agree. It also confuses matters when the newbie is suddenly given a library of IO code to use -- but told to ignore it -- they suddenly start wondering why it is so difficult to do anything "useful" in Haskell. A consequence of which seems that the student becomes afraid (and ignorant) of Haskell. > I find that the Haskell introductions I like the most are the ones > that accompany papers about STM and such. I.e. ones which have to > teach the reader about the basics of Haskell IO, but doesn't have > enough space to start with the pretty stuff. I agree with this also. I don't think it is a difficult feat teaching an absolute beginner how do some some basic stuff with the IO monad. This shows straight away that haskell can do some useful stuff other than adding numbers together in Hugs. >Mix that with some actual > comutations to show off some pretty stuff and you'll have a newbie who > is both excited about the cool looking features of the pure aspects of > Haskell, but completely aware of the fact that you can do impure stuff > as well. Yes, I wish this approach was applied much more often. Semi-related to this: I taught an algorithms and data structures class last term. In one of the classes the students were given an equation to solve and they were frantically typing it into their calculators, replacing the variable parameters with numbers. I told them they could all finish the class in 5 minutes if they used Haskell. Type the equation as it is and use higher-order functions to work out the parameters. The look of horror on the student's faces when I mentioned the 'H' word was priceless. However, they were all prepared to spend 50 minutes writing a Java program which would have the same effect. Chris. From tom.davie at gmail.com Wed Jan 3 15:01:43 2007 From: tom.davie at gmail.com (Thomas Davie) Date: Wed Jan 3 14:58:25 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> References: <459BBE4A.20902@ropine.com> <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> Message-ID: > > It's true that this is the typical way of learning Haskell, but I for > one think it's a bad way of learning Haskell. > Very few real world programs get by without the "impure" stuff, so if > you give the newbie the impression that it isn't there (by postponing > it) there's a chance he'll run into a situation where he needs it > before it's been even mentioned (queue newbie going "bah, academic > language" and switching to C++). On the contrary, I think it's an excellent way of learning Haskell. I'm writing a lot of useful Haskell code with only one IO action (interact). I don't think I could reasonably construct an introductory problem that couldn't be solved with it, and I haven't yet found an application for which I've needed more. I think it's destructive to teach people "we have a wonderful new paradigm of programming that solves all sorts of problems, but all we're going to use it for is doing what we did with C++ anyway". That's just my 2? -- I like Haskell specifically because I don't have to do things in order and I don't have to do things in an imperative style, I would love for more people to be taught about this wonderful thing. Bob From ndmitchell at gmail.com Wed Jan 3 15:14:14 2007 From: ndmitchell at gmail.com (Neil Mitchell) Date: Wed Jan 3 15:10:40 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: References: <459BBE4A.20902@ropine.com> <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> Message-ID: <404396ef0701031214t5f6113b6ma44f5a8f6f9d708c@mail.gmail.com> Hi > On the contrary, I think it's an excellent way of learning Haskell. > I'm writing a lot of useful Haskell code with only one IO action > (interact). I don't think I could reasonably construct an > introductory problem that couldn't be solved with it, and I haven't > yet found an application for which I've needed more. I think interact is a bit ugly. Most introductory problems are "take a small amount of data, do something". In that case using Hugs/GHCi with :main arguments to give in the arguments, getArgs to read them and putStrLn to show the results is a very beautiful and does about all that you need. Very few programs are actually interactive - if they are they should usually get a GUI. As for beginner issues with rank-2 types, I've been learning Haskell for years now, and have never felt the need for a rank-2 type. If the interface for some feature requires rank-2 types I'd call that an abstraction leak in most cases. It certainly means that you can't properly Hoogle for it, can't compile it with Yhc, can't do full type inference etc. Thanks Neil From cmb21 at kent.ac.uk Wed Jan 3 15:16:58 2007 From: cmb21 at kent.ac.uk (C.M.Brown) Date: Wed Jan 3 15:13:36 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: References: <459BBE4A.20902@ropine.com> <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> Message-ID: Hi, > On the contrary, I think it's an excellent way of learning Haskell. > I'm writing a lot of useful Haskell code with only one IO action > (interact). I don't think I could reasonably construct an > introductory problem that couldn't be solved with it, and I haven't > yet found an application for which I've needed more. I think it's > destructive to teach people "we have a wonderful new paradigm of > programming that solves all sorts of problems, but all we're going to > use it for is doing what we did with C++ anyway". Yes, but the point is most students have already been poisoned with C++ (or Java). They don't see the point in Haskell becuase they can't see the wood for the trees. The only way to get them interested in Haskell in the first place is to make it look vaguely like C++ (or Java) -- it's like coercing a Donkey with a carrot. Once they are interested - show them there is a lot more to Haskell than imperative-style behaviour, that way they may also see the elegence of purely functional programming. > That's just my 2? -- I like Haskell specifically because I don't have > to do things in order and I don't have to do things in an imperative > style, I would love for more people to be taught about this wonderful > thing. So would I. But in reality it just doesn't seem to work like that. Chris. From igloo at earth.li Wed Jan 3 17:07:15 2007 From: igloo at earth.li (Ian Lynagh) Date: Wed Jan 3 17:03:43 2007 Subject: [Haskell-cafe] State separation/combination pattern question In-Reply-To: References: Message-ID: <20070103220715.GA25860@matrix.chaos.earth.li> Hi Reto, On Thu, Dec 21, 2006 at 10:11:22PM -0800, Reto Kramer wrote: > > I've tried to thread the two states (StateA and StateB) using a chain > of StateT ... StateT ..., but couldn't really make that work. That is how I would write it; I have attached code for your example. > It > seems rather arbitrary in this case which state to make the inner/ > outer one The choice is indeed arbitrary. > and depending on this ordering the "lifts" have to go with > one or the other set of store calls. If you don't mind turning on overlapping and undecidable instances then you don't need to manually lift things at all. Thanks Ian -------------- next part -------------- {-# OPTIONS_GHC -fglasgow-exts -fallow-overlapping-instances -fallow-undecidable-instances #-} import Control.Monad.Trans (MonadTrans) import Control.Monad.State (StateT, evalStateT, get, put, lift) -- StateA type StateA = [Integer] newtype MonadAT m a = MonadAT (StateT StateA m a) deriving (Monad, MonadTrans) class Monad m => MonadA m where getA :: m StateA putA :: StateA -> m () instance Monad m => MonadA (MonadAT m) where getA = MonadAT get putA = MonadAT . put instance (MonadTrans t, MonadA m, Monad (t m)) => MonadA (t m) where getA = lift getA putA = lift . putA evalAT :: Monad m => MonadAT m a -> StateA -> m a evalAT (MonadAT x) = evalStateT x -- StateB type StateB = [Integer] newtype MonadBT m a = MonadBT (StateT StateB m a) deriving (Monad, MonadTrans) class Monad m => MonadB m where getB :: m StateB putB :: StateB -> m () instance Monad m => MonadB (MonadBT m) where getB = MonadBT get putB = MonadBT . put instance (MonadTrans t, MonadB m, Monad (t m)) => MonadB (t m) where getB = lift getB putB = lift . putB evalBT :: Monad m => MonadBT m a -> StateB -> m a evalBT (MonadBT x) = evalStateT x -- The program type Monads = MonadBT (MonadAT IO) main :: IO () main = do res <- evalAT (evalBT exec []) [] print res exec :: Monads (StateA, StateB) exec = do foo bar foo foo bar a <- getA b <- getB return (a, b) foo :: MonadA m => m () foo = do st <- getA putA (1 : st) bar :: MonadB m => m () bar = do st <- getB putB (2 : st) From zunino at di.unipi.it Wed Jan 3 18:38:59 2007 From: zunino at di.unipi.it (Roberto Zunino) Date: Wed Jan 3 18:35:46 2007 Subject: [Haskell-cafe] Monad Set via GADT Message-ID: <459C3E93.1040909@di.unipi.it> To improve my understanding of GADT, I tried to define a Set datatype, with the usual operations, so that it can be made a member of the standard Monad class. Here I report on my experiments. First, I recap the problem. Data.Set.Set can not be made a Monad because of the Ord constraint on its parameter, while e.g. (return :: a -> m a) allows any type inside the monad m. This problem can be solved using an alternative monad class (restricted monad) so that the Ord context is actually provided for the monad operations. Rather, I aimed for the standard Monad typeclass. To avoid reinventing Data.Set.Set, my datatype is based on that. Basically, when we know of an Ord context, we use a Set. Otherwise, we use a simple list representation. Using a list is just enough to allow the implementation of return (i.e. (:[])) and (>>=) (i.e. map and (++)), so while not being very efficient, it is simple. Other non-monadic operators require an Ord context, so that we can turn lists into Set. My first shot at this was: data SetM a where L :: [a] -> SetM a SM :: Ord a => Set.Set a -> SetM a However, this was not enough to convince the type checker to use the Ord context stored in SM. Specifically, performing union with union (SM m1) (SM m2) = SM (m1 `Set.union` m2) causes GHC to report "No instance for (Ord a)". After some experiments, I found the following, using a type equality witness: data Teq a b where Teq :: Teq a a data SetM a where L :: [a] -> SetM a SM :: Ord w => Teq a w -> Set.Set w -> SetM a Now if I use union (SM p1 m1) (SM p2 m2) = case (p1,p2) of (Teq,Teq) -> SM Teq (m1 `Set.union` m2) it typechecks! This rises some questions I cannot answer: 1) Why the first version did not typececk? 2) Why the second one does? 3) If I replace (Teq a w) with (Teq w a), as in SM :: Ord w => Teq w a -> Set.Set w -> SetM a then union above does not typecheck! Why? I guess the type variable unification deriving from matching Teq is not symmetric as I expect it to be... Below, I attach the working version. Monad and MonadPlus instances are provided for SetM. Conversions from/to Set are also provided, requiring an Ord context. "Efficient" return and mzero are included, forcing the Set representation to be used, and requiring Ord (these could also be derived from fromSet/toSet, however). Comments are very welcome, of course, as well as non-GADT related alternative approaches. Regards, Roberto Zunino. ============================================================ \begin{code} {-# OPTIONS_GHC -Wall -fglasgow-exts #-} module SetMonad ( SetM() , toSet, fromSet , union, unions , return', mzero' ) where import qualified Data.Set as S import Data.List hiding (union) import Control.Monad -- Type equality witness data Teq a b where Teq :: Teq a a -- Either a list or a real Set data SetM a where L :: [a] -> SetM a SM :: Ord w => Teq a w -> S.Set w -> SetM a instance Monad SetM where return = L . (:[]) m >>= f = case m of L l -> unions (map f l) SM Teq s -> unions (map f (S.toList s)) instance MonadPlus SetM where mzero = L [] mplus = union -- Efficient variants for Ord types return' :: Ord a => a -> SetM a return' = SM Teq . S.singleton mzero' :: Ord a => SetM a mzero' = SM Teq S.empty -- Set union: use the best representation union :: SetM a -> SetM a -> SetM a union (L l1) (L l2) = L (l1 ++ l2) union (SM p1 m1) (SM p2 m2) = case (p1,p2) of (Teq,Teq) -> SM Teq (m1 `S.union` m2) union (L l1) (SM p m2) = case p of Teq -> SM Teq (m2 `S.union` S.fromList l1) union s1 s2 = union s2 s1 -- Try to put a SM first before folding, to improve performance unions :: [SetM a] -> SetM a unions = let isSM (SM _ _) = True isSM _ = False in foldl' union (L []) . uncurry (++) . break isSM -- Conversion from/to Set requires Ord toSet :: Ord a => SetM a -> S.Set a toSet (L l) = S.fromList l toSet (SM p m) = case p of Teq -> m fromSet :: Ord a => S.Set a -> SetM a fromSet = SM Teq -- Tests test :: IO () test = do let l = [1..3] :: [Int] s = fromSet (S.fromList l) g x = return' x `mplus` return' (x+100) print $ S.toList $ toSet $ do x <- s y <- s return' (x+y) -- [2,3,4,5,6] print $ S.toList $ toSet $ do x <- s g x -- [1,2,3,101,102,103] print $ S.toList $ toSet $ do x <- s y <- g x return' y -- [1,2,3,101,102,103] print $ S.toList $ toSet $ do x <- s y <- g x g y -- [1,2,3,101,102,103,201,202,203] print $ S.toList $ toSet $ do x <- s y <- return (const x) -- no Ord! return' (y ()) -- [1,2,3] \end{code} From dons at cse.unsw.edu.au Wed Jan 3 20:11:53 2007 From: dons at cse.unsw.edu.au (Donald Bruce Stewart) Date: Wed Jan 3 20:08:22 2007 Subject: [Haskell-cafe] darcs repo for yampa + gadt In-Reply-To: References: Message-ID: <20070104011153.GA12938@cse.unsw.EDU.AU> joelr1: > Folks, > > I have a version of Yampa with Henrik Nilsson's GADT optimizations > that I cleaned up for ghc 6.6 and cabalized. Would it be possible to > set it up at darcs.haskell.org and if so how should I go about it? > There are some details here: http://haskell.org/haskellwiki/How_to_write_a_Haskell_program If you hang on a couple of weeks, you should be able to upload it to the hackage database. -- Don From zunino at di.unipi.it Wed Jan 3 21:28:05 2007 From: zunino at di.unipi.it (Roberto Zunino) Date: Wed Jan 3 21:24:34 2007 Subject: [Haskell-cafe] GADT proofs of FunDeps? Message-ID: <459C6635.4030605@di.unipi.it> I am investigating mixing FunDeps with the type equality GADT data Teq a b where Teq :: Teq a a Basically, I would like to write something like proof :: (C a b1, C a b2) => Teq b1 b2 proof = unsafeCoerce# Teq provided the FunDep class C a b | a -> b Is this safe? Any caveat? Regards, Roberto Zunino. From p.f.moore at gmail.com Thu Jan 4 03:53:46 2007 From: p.f.moore at gmail.com (Paul Moore) Date: Thu Jan 4 03:50:11 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <459BE494.9040603@ropine.com> References: <459BBE4A.20902@ropine.com> <459BE494.9040603@ropine.com> Message-ID: <79990c6b0701040053p21a51f48j5f0e6a2dc3dd8b32@mail.gmail.com> On 1/3/07, Seth Gordon wrote: > David House wrote: > > > >> So I can't just tell someone who's just starting to learn Haskell that > >> "f $ g y" is equivalent to "f (g y)"; I have to say "those two are > >> *almost always* equivalent, but if you use $ and the compiler complains > >> about not being able to match the expected and the inferred type and a > >> type signature in the error message has the word 'forall', try rewriting > >> that expression without the $ and see if it compiles". Eeeww. > > > > Why would someone just starting to learn Haskell be using ST? The > > canonical tutorial structure is to start with the pure stuff and only > > introduce the (more complicated!) impure stuff (ST, IORefs, etc.) in > > an 'advanced techniques' or similar section. > > I (and one other person on this list) ran into this issue when I was > trying to use takusen to make Haskell talk to a RDBMS. You obviously > need to learn advanced techniques to *implement* such a thing, but you > shouldn't need advanced knowledge to *use a library* that happens to use > higher-rank polymorphic types in its API. That other person was me, and I agree entirely. I have a little sample project, using databases and concurrency, which I wanted to rewrite in Haskell, as a learning exercise. I hit exactly this issue when simply trying out some sample code, and my reaction was very much one of irritation, frustration and confusion. One of the nice things about Haskell, coming to it from an imperative POV, is that monads can be thought of a little like first-class composable "statement blocks". When I understood that, I had a real "hey, that's neat!" reaction. One of the nasty things about Haskell (at my level of experience) is that your nice helpful intuitions about monads can break down into real confusion when you hit complex monads, monad transformers and the like - *and you hit them quite early in the APIs of some libraries*! It's not a big deal, but it's a bit offputting for a newcomer. Paul. From p.f.moore at gmail.com Thu Jan 4 04:03:03 2007 From: p.f.moore at gmail.com (Paul Moore) Date: Thu Jan 4 03:59:27 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <404396ef0701031214t5f6113b6ma44f5a8f6f9d708c@mail.gmail.com> References: <459BBE4A.20902@ropine.com> <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> <404396ef0701031214t5f6113b6ma44f5a8f6f9d708c@mail.gmail.com> Message-ID: <79990c6b0701040103j544eb6f4x21331a295891011e@mail.gmail.com> On 1/3/07, Neil Mitchell wrote: > As for beginner issues with rank-2 types, I've been learning Haskell > for years now, and have never felt the need for a rank-2 type. If the > interface for some feature requires rank-2 types I'd call that an > abstraction leak in most cases. It certainly means that you can't > properly Hoogle for it, can't compile it with Yhc, can't do full type > inference etc. That may well be true. Something I forgot to mention in my previous posting was that I'm not 100% convinced that the issue I hit with Takusen isn't a problem with the library - I find it very hard to read or understand some parts of the library documentation, basically because the types seem so complex. My intuition says that reading a database is logically similar to reading a file, so types like doQuery :: (Statement stmt sess q, QueryIteratee (DBM mark sess) q i seed b, IQuery q sess b) => stmt -> i -> seed -> DBM mark sess seed look pretty baffling to me - and don't match my intuition that main = do withSession (connect "user" "password" "server") $ do -- simple query, returning reversed list of rows. r <- doQuery (sql "select a, b, c from x") query1Iteratee [] liftIO $ putStrLn $ show r otherActions session is "basically I/O". (Oh, by the way - that "$" on the withSession line is the one that caused the error which started this thread...) Paul. From gale at sefer.org Thu Jan 4 04:25:41 2007 From: gale at sefer.org (Yitzchak Gale) Date: Thu Jan 4 04:22:04 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <404396ef0701031214t5f6113b6ma44f5a8f6f9d708c@mail.gmail.com> References: <459BBE4A.20902@ropine.com> <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> <404396ef0701031214t5f6113b6ma44f5a8f6f9d708c@mail.gmail.com> Message-ID: <2608b8a80701040125y3f2b8fc9vcd0d79b73c4056fe@mail.gmail.com> Seth Gordon wrote: > From a friendliness-to-newbies point of view, > these error messages are a tremendous wart... > Eeeww. Neil Mitchell wrote: > If the interface for some feature requires rank-2 > types I'd call that an abstraction leak in most cases. As the original poster of this thread, the one who was bitten this time, let me point out that the use of rank-2 polymorphism here is actually really nice. It provides a strong safety guarantee for the ST monad at *compile time*. But the protection is a bit heavy-handed, so there are some painful side effects that need to be addressed. One is the confusion caused by the strange semantics to those not familiar with the theory. That should be fixed by simple, prominant, task-oriented documentation. ("You must always provide runST with an argument. So, for example, you cannot write "runST $" or "runST .".) And yes, perhaps the error messages in GHC could be improved for newbies, but that was never intended to be the strong point of GHC. I think Hugs is fine here. The other is awkwardness in extending the capabilites of ST. For that, I would propose that the function "unsafeRunST" be added to the library. Of course, if there is some way to improve both of these situations by compilers relaxing the restrictions on rank-2 types somewhat, that would be great. But that is probably for the future. -Yitz From gale at sefer.org Thu Jan 4 04:43:42 2007 From: gale at sefer.org (Yitzchak Gale) Date: Thu Jan 4 04:40:06 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <79990c6b0701040053p21a51f48j5f0e6a2dc3dd8b32@mail.gmail.com> References: <459BBE4A.20902@ropine.com> <459BE494.9040603@ropine.com> <79990c6b0701040053p21a51f48j5f0e6a2dc3dd8b32@mail.gmail.com> Message-ID: <2608b8a80701040143p574a2216gb342f1852f67ed04@mail.gmail.com> Paul Moore wrote: > ...your nice helpful intuitions about monads can break down into > real confusion when you hit complex monads, monad transformers and the > like - *and you hit them quite early in the APIs of some libraries*! I don't think that is a problem with the design of the libraries. It is a problem with the documentation. Almost all library documentation could be written so that any user could easily use the library in a simple, practical, straightforward way. I am not saying that it would be easy, but it could be done. Nowadays, that type of documentation is taken for granted for every popular programming language. -Yitz From apfelmus at quantentunnel.de Thu Jan 4 05:21:22 2007 From: apfelmus at quantentunnel.de (apfelmus@quantentunnel.de) Date: Thu Jan 4 05:20:10 2007 Subject: [Haskell-cafe] Re: Composing functions with runST In-Reply-To: <404396ef0701031214t5f6113b6ma44f5a8f6f9d708c@mail.gmail.com> References: <459BBE4A.20902@ropine.com> <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> <404396ef0701031214t5f6113b6ma44f5a8f6f9d708c@mail.gmail.com> Message-ID: Neil Mitchell wrote: > As for beginner issues with rank-2 types, I've been learning Haskell > for years now, and have never felt the need for a rank-2 type. If the > interface for some feature requires rank-2 types I'd call that an > abstraction leak in most cases. It certainly means that you can't > properly Hoogle for it, can't compile it with Yhc, can't do full type > inference etc. I think that the term "abstraction leak" is too harsh. In some sense, you may as well call "strong typing" an "abstraction leak" because one can do the stuff as well in a dynamic typed language and adding strong typing means that you can't compile it with current compilers, you need to implement type checking/inference etc. Of course, this analogy has flaws as higher rank types go to the edge of computability whereas strong typing can be implemented. Concerning interfaces, higher rank types offer crucial static checking that cannot be achieved without them. The prominent example is ST. The next example is the parsing library "frisby". In both cases, it would be easy to wrack havoc in case the interface would not use higher rank types. The same analogy as above applies: one uses strong typing because one does not want to wreak havoc. I would not call this an "abstraction leak". Concerning implementation, higher rank types are even more widespread: almost everything involving continuations needs them: ReadP, Exceptions (as opposed to Either), deforestation etc. In fact, it is quite possible to throw away algebraic data types altogether and build everything you need with higher rank types. A prominent example is [a] ~= (forall b . (a -> b -> b) -> b -> b) ~= (forall b . (Maybe (a,b) -> b) -> b) The denotational semantics do not change, but the time and space behavior is much different. Perhaps the above remarks misinterpret your statement and you meant "abstraction leak" in the sense that, because higher rank types are available, the interface author used them without thinking whether the same effect can be achieved in ordinary Haskell. Alas, such problems are not tied to higher rank types: proper interface design is an art and does not come for free, not to mention interface documentation[1]. One could easily berserk: why does this library use String and doesn't abstract it with a type class? Why does that interface only provide IO, why isn't this available as a library of pure functions? What do these obviously crappy semantics mean? In this case, higher rank types are a symptom, not the problem. If one wants to cure the problem by disallowing the symptom, then I suggest to also erase the symptom IO. Thoroughly. Of course, the drawbacks of higher rank types you mentioned remain. In the case of "hoogleability", I'm confident that it is possible to implement them, it's only that someone has to think hard about it. Implementing higher rank types in YHC is even harder but not impossible. Sure, type inference is the most difficult thing, and one has to accept glitches and drawbacks to make it work. Compared to these difficulties, I think that the remark > So I can't just tell someone who's just starting to learn Haskell that > "f $ g y" is equivalent to "f (g y)"; I have to say "those two are > *almost always* equivalent, but if you use $ and the compiler complains > about not being able to match the expected and the inferred type and a > type signature in the error message has the word 'forall', try rewriting > that expression without the $ and see if it compiles". Eeeww. posted in this tread is too harsh. That's life, every language has its flaws and glitches: parts of the layout rule, pattern guards, I want a better records system, views, generic programming, etc. But, when code has to be finished, those glitches or annoying things are best countered with a shrug: they are not life-threatening. A programming language with nonexistent type system and ugly semantics is. And much to our joy, Haskell is far from this. In that sense, dear reader of this post, just rewrite that expression without $ and see if it compiles. The complier authors don't want to annoy you, it's just that the exact reasons why this cannot yet be put to work are damn hard. You are encouraged to learn about System F to get a grasp of what is going on, but spending this one $ will be much cheaper. Regards, apfelmus [1] Concerning library documentation, I think that literate Haskell sources have the drawback that they are either tied to TeX (\begin{code}..\end{code}) or that every line has to start with a '>'. I'd suggest to add a .. or something else. The point is that while (La)TeX can be cranked up to a publishing system, it is not suited for many tasks such as media-dependent processing. TeX is a macro language, not a structured document type. And for the strongly typed Haskell programmer used to referential transparency, macros are a nightmare. From gale at sefer.org Thu Jan 4 05:40:57 2007 From: gale at sefer.org (Yitzchak Gale) Date: Thu Jan 4 05:37:20 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <20070103130320.GA1542@web.de> References: <4599114D.6020603@cs.nott.ac.uk> <2608b8a80701011043m2f8e3519mf443833876076245@mail.gmail.com> <20070101203246.GB1488@web.de> <2608b8a80701011630h1db56cbag9ae608d374ba8c80@mail.gmail.com> <20070103130320.GA1542@web.de> Message-ID: <2608b8a80701040240n4faecb5er8fb2e51d4792c7e7@mail.gmail.com> I wrote: >> Combining ST and MTL can be messy, even in this simple >> case. You will probably write something with a type like >> RandomGen g => [a] -> g -> ST s ([a], g) Udo Stenzel wrote: > But why would you even want to do this? It's ugly and cumbersome. Yes indeed. > You'd plug a runST in there and get > shuffle :: RandomGen g => [a] -> g -> ([a], g) Yes. In fact, that is what I did in practice. As you say, the overall effect is ugly and cumbersome. And this is with only the simplest of stateful calculations. I shudder to think about what happens when things are more complex. That is why I am thinking that - >> Wouldn't it be nice if instead you could just write: >> >> shuffle :: (RandomGen g, MonadState g m) => [a] -> m [a] >> shuffle = stToState . shuffleST and then just use that directly inside a calculation that is otherwise purely non-ST? > It seems, what you really want is > shuffleST :: RandomGen g => [a] -> StateT g ST [a] Actually, I tried that. It didn't help - it was just one more layer I had to peel away to get at the ST inside. There seems to be no way to avoid the fact that you think about state in two very different ways in these two monads. Every program is written in either one style or the other. Occasionally, you require an isolated use of the opposite style, and I am looking for ways of simplifying the resulting mess. "StateT st ST" and "MonadST" look like ways of combining the two, but in practice I find that they just seem to get in the way. I am starting to be convinced that the only way to write the function I want is by using unsafeRunST. Or type it as stToState :: MonadState st m => (st -> ST s (a, st)) -> m a and then write in the documentation that the user is require to write do r <- newSTRef x ... y <- readSTRef r return (z, y) by hand every time. Yuck. Am I missing something? -Yitz From apfelmus at quantentunnel.de Thu Jan 4 06:49:18 2007 From: apfelmus at quantentunnel.de (apfelmus@quantentunnel.de) Date: Thu Jan 4 06:48:18 2007 Subject: [Haskell-cafe] Re: Composing functions with runST In-Reply-To: <2608b8a80701040240n4faecb5er8fb2e51d4792c7e7@mail.gmail.com> References: <4599114D.6020603@cs.nott.ac.uk> <2608b8a80701011043m2f8e3519mf443833876076245@mail.gmail.com> <20070101203246.GB1488@web.de> <2608b8a80701011630h1db56cbag9ae608d374ba8c80@mail.gmail.com> <20070103130320.GA1542@web.de> <2608b8a80701040240n4faecb5er8fb2e51d4792c7e7@mail.gmail.com> Message-ID: Yitzchak Gale wrote: > Well, it turns out that using Data.Sequence or Data.IntMap > to shuffle a list becomes prohibitive if you might have > more than about 10^5 elements in your list. So in that > case you will need to use a mutable array, and you now > need ST. > [..] > >>> Wouldn't it be nice if instead you could just write: >>> >>> shuffle :: (RandomGen g, MonadState g m) => [a] -> m [a] >>> shuffle = stToState . shuffleST > > and then just use that directly inside a calculation that > is otherwise purely non-ST? > >> It seems, what you really want is >> shuffleST :: RandomGen g => [a] -> StateT g ST [a] > > Actually, I tried that. It didn't help - it was just one more > layer I had to peel away to get at the ST inside. > > There seems to be no way to avoid the fact that you > think about state in two very different ways in these > two monads. Every program is written in either one style > or the other. Occasionally, you require an isolated use > of the opposite style, and I am looking for ways of simplifying > the resulting mess. "StateT st ST" and "MonadST" look like > ways of combining the two, but in practice I find that they > just seem to get in the way. I don't get what exactly you want. If you want to carry your state named "MyState" (f.i. type MyState = [Cards,Players]) around in a monad, you use "Control.Monad.State MyState". If (and only if) you have an algorithm (like depth-first search) that carries an array as state around (nodes already visited) and you know that this array is used in a single threaded fashion, it might be worth to update the array in place. For that, you use Control.Monad.ST and Data.Array.ST and you can be confident that the state carrying has been strictness analyzed and fine tuned to match the machine. In short, you get updates in place without selling your soul to IO, runST is your protection from evil and will keep you pure. ST does not really have more uses than this one (besides being the foundation for IO). For more info on ST, see http://research.microsoft.com/Users/simonpj/Papers/state-lasc.ps.gz Note that the you can now achieve the array thing as well with Data.Array.Diff. This is a purely functional interface to an array type that uses destructible updates internally and keeps a history to become persistent. However, I doubt that an array makes a difference over Data.IntMap for all but the most special cases. > I am starting to be convinced that the only way to > write the function I want is by using unsafeRunST. > Or type it as > > stToState :: MonadState st m => (st -> ST s (a, st)) -> m a > > and then write in the documentation that the > user is require to write > > do > r <- newSTRef x > ... > y <- readSTRef r > return (z, y) > > by hand every time. Yuck. If the programmer needs to adhere to a policy, the type system may well enforce it for him. No unsafeRunST. It's far better to struggle with the safety device than to discover the hard way that running without it will directly lead into the debugging hell. Regards, apfelmus From bulat.ziganshin at gmail.com Thu Jan 4 07:40:03 2007 From: bulat.ziganshin at gmail.com (Bulat Ziganshin) Date: Thu Jan 4 07:42:25 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <2608b8a80701040125y3f2b8fc9vcd0d79b73c4056fe@mail.gmail.com> References: <459BBE4A.20902@ropine.com> <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> <404396ef0701031214t5f6113b6ma44f5a8f6f9d708c@mail.gmail.com> <2608b8a80701040125y3f2b8fc9vcd0d79b73c4056fe@mail.gmail.com> Message-ID: <1808493025.20070104154003@gmail.com> Hello Yitzchak, Thursday, January 4, 2007, 12:25:41 PM, you wrote: > The other is awkwardness in extending the capabilites > of ST. For that, I would propose that the function "unsafeRunST" > be added to the library. this function exists, but named unsafeIOtoST. IO and ST is exactly the same things, the only difference that foreign imports may be marked as IO operations but both ST ones. as a result, ST is restricted to a few standard operations that guarantees to bo be mutually transparent for consumers of runST. when one goes to extend ST functionality, unsafeIOtoST is used. for 3xample, in Hugs it is used to convert peek/poke IO operations into STUArray implementation. except for compile-time type sugar, there is no difference between those two type constructors. unsafeIOtoST is like liftIO: unsafeIOtoST :: IO a -> ST s a -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com From gale at sefer.org Thu Jan 4 08:10:45 2007 From: gale at sefer.org (Yitzchak Gale) Date: Thu Jan 4 08:07:07 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <2608b8a80701040240n4faecb5er8fb2e51d4792c7e7@mail.gmail.com> References: <4599114D.6020603@cs.nott.ac.uk> <2608b8a80701011043m2f8e3519mf443833876076245@mail.gmail.com> <20070101203246.GB1488@web.de> <2608b8a80701011630h1db56cbag9ae608d374ba8c80@mail.gmail.com> <20070103130320.GA1542@web.de> <2608b8a80701040240n4faecb5er8fb2e51d4792c7e7@mail.gmail.com> Message-ID: <2608b8a80701040510x49f30e22vca428e7d39fcd5f9@mail.gmail.com> I wrote: > Am I missing something? Yes! In reality, I do not need unsafeSTRef for this at all, using a type suggested earlier by Udo: stToState :: MonadState st m => (forall s. STRef s st -> ST s a) -> m a stToState f = do s <- get let (y, s') = runST (stm f s) put s' return y where stm f s = do r <- newSTRef s y <- f r s' <- readSTRef r return (y, s') This works! Thanks, Udo! -Yitz From gale at sefer.org Thu Jan 4 08:25:06 2007 From: gale at sefer.org (Yitzchak Gale) Date: Thu Jan 4 08:21:30 2007 Subject: [Haskell-cafe] Composing functions with runST In-Reply-To: <1808493025.20070104154003@gmail.com> References: <459BBE4A.20902@ropine.com> <3d96ac180701031031u5a3d8d82g5392d25886270e48@mail.gmail.com> <404396ef0701031214t5f6113b6ma44f5a8f6f9d708c@mail.gmail.com> <2608b8a80701040125y3f2b8fc9vcd0d79b73c4056fe@mail.gmail.com> <1808493025.20070104154003@gmail.com> Message-ID: <2608b8a80701040525q68ec27coeb0e87569ac98052@mail.gmail.com> Hi Bulat, I wrote: >> One is the confusion caused by the strange semantics >> to those not familiar with the theory... Like me, of course. >> The other is awkwardness in extending the capabilites >> of ST. For that, I would propose that the function "unsafeRunST" >> be added to the library. Bulat Ziganshin wrote: > this function exists, but named unsafeIOtoST. That wasn't what I had in mind, because it forces the thread parameter to take the specific value RealWorld. But I am not sure anymore that it is needed. It turned out that my case was just another instance of the first kind of awkwardness. So I no longer have any evidence that the second kind of awkwardness exists. So I withdraw my proposal. Thanks, Yitz From paolo.veronelli at gmail.com Thu Jan 4 08:25:16 2007 From: paolo.veronelli at gmail.com (Paolo Veronelli) Date: Thu Jan 4 08:25:43 2007 Subject: [Haskell-cafe] Arrays performance In-Reply-To: <20070103183820.GA1487@paolino.selfip.org> References: <20070101173004.GB1405@paolino.selfip.org> <20070101191621.GA1488@web.de> <20070103183820.GA1487@paolino.selfip.org> Message-ID: <20070104132516.GA1634@paolino.selfip.org> Quoting Paolo Veronelli : > I paste new version in case you care give me some moe suggestion. import Data.Maybe import Data.List import Data.Array.Diff import System.Environment import Control.Arrow import Control.Monad import Random inc l i = l // [(i,l!i + 1)] switch l i = l // [(i,not (l!i))] constArray n v = listArray (0,n-1) (repeat v) data Folding = Folding {clusters :: [(Int,Int)], remi :: Int, colsCount :: DiffArray Int Int ,rowsCheck :: DiffArray Int Bool} result (Folding cs _ _ _) = cs rcluster ls d s = let devil s@(Folding cs r hs fs) l@(row,col) = let ns = s { clusters = (l:cs), rowsCheck = switch fs row, colsCount = inc hs col } rowtest | c < d = ns | (c == d) && (r > 0) = ns { remi = r - 1 } | otherwise = s where c = hs ! col in if (not (fs ! row)) then rowtest else s in foldl devil s ls mcluster :: (Int,Int) -> [(Int,Int)] -> [(Int,[Int])] mcluster (lr,lc) ls = let (k,r) = divMod lr lc start = Folding{clusters = [],remi = r,colsCount = constArray lc 0,rowsCheck = constArray lr False } cs = result $ rcluster ls k start in map collapse . groupBy (comp fst (==)) . sort . map swap $ cs where comp f g x y = (f x) `g` (f y) swap = snd &&& fst collapse = (head &&& unzip) >>> (fst *** snd) cluster :: (Ord b) => (a -> a -> b) -> [a] -> [a] -> [(a,[a])] cluster fxy xs ys = let mkArray (l,xs) = (listArray :: (Int,Int) -> [e] -> DiffArray Int e) (0,l-1) xs xls = mkArray (lc,xs) yls = mkArray (rc,ys) (lc,rc) = (length xs,length ys) in map ((yls !) *** map (xls !)) (mcluster (lc,rc) (snd.unzip.sort $ delta)) where delta = [(fxy x y,(n,m))|(n,x) <- zip [0..] xs, (m,y) <- zip [0..] ys] -- call it with 2 args, the number ov values and the number of clusters -- 101 10 will cluster 101 values in 10 clusters points m n = do gen <- getStdGen return $ splitAt n (take (m + n) (randomRs (0,100::Int) gen)) test1 = do args <- getArgs return $ map read args :: IO [Int] main = do