[Haskell-cafe] Re: optimization help
I think that you misunderstood what I said. When we went from FRP to Yampa, we changed from using signals directly, i.e. Signal a, to using signal functions, i.e.: SF a b = Signal a - Signal b When we did this, we made SF abstract, and we adopted the arrow framework to allow composing, etc. signal functions. This meant that you could not get your hands on Signals directly, which helped to prevent space leaks. What you describe above is a change that we made in the /implementation/ of signal functions (specifically, from streams to continuations), which indeed is an entirely different thing. You mean that only the fact that (Signal a - Signal b) got abstract prevented space leaks? Can you give an example? That the implementation with continuations avoids space leaks is clear. The question is whether the old does when using the new primitives. In fact, this amounts to the question whether (inject) as defined in newtype SF' a b = SF' ([a] - [b]) data SF a b = SF (a - (b, SF a b)) inject :: SF a b - SF' a b inject (SF f) (a:as) = let (b,g) = f a in b:inject g as preserves space and time complexity: inject (sf `o` sf') =same space time= (inject sf) . (inject sf') and the same for all other operations you provide besides `o`. Regards, apfelmus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Automatic fixity allocation for symbolic operators
On Mon, 16 Oct 2006, Jón Fairbairn [EMAIL PROTECTED] wrote: I made a more concrete proposal later and Phil Wadler tidied it up. I think It even got as far as a draft of the language, [...] Do you know where this proposal/draft can be found? -- /NAD ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Automatic fixity allocation for symbolic operators
Nils Anders Danielsson [EMAIL PROTECTED] writes: On Mon, 16 Oct 2006, Jón Fairbairn [EMAIL PROTECTED] wrote: I made a more concrete proposal later and Phil Wadler tidied it up. I think It even got as far as a draft of the language, [...] Do you know where this proposal/draft can be found? On the fplangc mailing list. Thomas Johnsson has the archive, but as it was a closed mailing list I don't know if it's OK to publish the URL. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] getting a DB library working with ghc 6.6 and PostgreSQL 7.4.7
I installed HDBC, but when I tried running a simple program that used it, I get the error message ghc-6.6: /usr/local/lib/HDBC-postgresql-1.0.1.0/ghc-6.6/HSHDBC-postgresql-1.0.1.0.o: unknown symbol `PQserverVersion' Ah, I figured it out. The PQserverVersion function is documented in the PostgreSQL 8.0 and 8.1 manuals as follows: Applications may use this to determine the version of the database server they are connected to. The number is formed by converting the major, minor, and revision numbers into two-decimal-digit numbers and appending them together. For example, version 7.4.2 will be returned as 70402, and version 8.1 will be returned as 80100 (leading zeroes are not shown). Zero is returned if the connection is bad. You'd think, from the description, that the libpq for PostgreSQL 7.4 would also have this function. But it doesn't. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Newbie and working with IO Int and Int
Hi all, I'm really newbie to Haskell, and working on a program I'm trying to make some testing. I make some test on certain know values ( e.g. adding 10 to 15 must return 25) and some test on random values (eg. adding rnd1 to rnd2 must return rnd1+rnd2). The problem that makes me mad is the random number generation. I can obtain random numbers through module Random but all of them return IO Int values (all I need are Ints) instead of Int. I know that I can adjust my own functions to use IO Int instead of Int but the call to certain functions must contain Int parameters, because these ones can't be changed to accept IO Int (I read http://haskell.org/hawiki/ThatAnnoyingIoType and know that can convert from IO Int to Int :-P). How can I deal with this problem ?? Thanks in advance. -- Víctor A. Rodríguez (http://www.bit-man.com.ar) El bit Fantasma (Bit-Man) Perl Mongers Capital Federal (http://cafe.pm.org/) GNU/Linux User Group - FCEyN - UBA (http://glugcen.dc.uba.ar/) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Newbie and working with IO Int and Int
Víctor A. Rodríguez wrote: Hi all, I'm really newbie to Haskell, and working on a program I'm trying to make some testing. I make some test on certain know values ( e.g. adding 10 to 15 must return 25) and some test on random values (eg. adding rnd1 to rnd2 must return rnd1+rnd2). The problem that makes me mad is the random number generation. I can obtain random numbers through module Random but all of them return IO Int values (all I need are Ints) instead of Int. I know that I can adjust my own functions to use IO Int instead of Int but the call to certain functions must contain Int parameters, because these ones can't be changed to accept IO Int (I read http://haskell.org/hawiki/ThatAnnoyingIoType and know that can convert from IO Int to Int :-P). What's wrong with doing it this way? -- ** UNTESTED CODE ** verifyAdd :: Int - Int - Int - Bool verifyAdd a b sum | a + b == sum = True otherwise= False testAddMundane :: Int - Int - Bool testAddMundane a b = verifyAdd a b (a + b) -- all the IO-dependent stuff is below this line -- testAddRandom :: IO Bool testAddRandom = do a - randomIO b - randomIO return verifyAdd a b (a + b) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Newbie and working with IO Int and Int
On Oct 17, 2006, at 12:21 PM, Víctor A. Rodríguez wrote: Hi all, I'm really newbie to Haskell, and working on a program I'm trying to make some testing. I make some test on certain know values ( e.g. adding 10 to 15 must return 25) and some test on random values (eg. adding rnd1 to rnd2 must return rnd1+rnd2). Probably the best way to deal with this is to use the QuickCheck library. http://www.cs.chalmers.se/~rjmh/QuickCheck/ It makes this sort of thing fairly painless, because you don't have to muck about with generating random data manually. The problem that makes me mad is the random number generation. I can obtain random numbers through module Random but all of them return IO Int values (all I need are Ints) instead of Int. I know that I can adjust my own functions to use IO Int instead of Int but the call to certain functions must contain Int parameters, because these ones can't be changed to accept IO Int (I read http://haskell.org/hawiki/ThatAnnoyingIoType and know that can convert from IO Int to Int :-P). How can I deal with this problem ?? See: http://www.haskell.org/ghc/dist/current/docs/libraries/base/ System-Random.html If you use 'getStdGen' or 'newStdGen' (which are in the IO monad), then you can later use the pure functions 'random', 'randomR' and friends. Alternately, you can manually seed the PRNG with 'mkStdGen' and avoid the IO monad altogether. Thanks in advance. -- Víctor A. Rodríguez (http://www.bit-man.com.ar) El bit Fantasma (Bit-Man) Perl Mongers Capital Federal (http://cafe.pm.org/) GNU/Linux User Group - FCEyN - UBA (http://glugcen.dc.uba.ar/) Rob Dockins Speak softly and drive a Sherman tank. Laugh hard; it's a long way to the bank. -- TMBG ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Newbie and working with IO Int and Int
On Tue, Oct 17, 2006 at 01:21:38PM -0300, V?ctor A. Rodr?guez wrote: To: haskell-cafe@haskell.org From: Víctor A. Rodríguez [EMAIL PROTECTED] Date: Tue, 17 Oct 2006 13:21:38 -0300 Subject: [Haskell-cafe] Newbie and working with IO Int and Int Hi all, I'm really newbie to Haskell, and working on a program I'm trying to make some testing. I make some test on certain know values ( e.g. adding 10 to 15 must return 25) and some test on random values (eg. adding rnd1 to rnd2 must return rnd1+rnd2). The problem that makes me mad is the random number generation. I can obtain random numbers through module Random but all of them return IO Int values (all I need are Ints) instead of Int. I know that I can adjust my own functions to use IO Int instead of Int but the call to certain functions must contain Int parameters, because these ones can't be changed to accept IO Int (I read http://haskell.org/hawiki/ThatAnnoyingIoType and know that can convert from IO Int to Int :-P). How can I deal with this problem ?? you should probably keep reading on. (-: have you seen the stuff on the new wiki? http://www.haskell.org/haskellwiki/Books_and_tutorials#Using_monads short answer: the type IO Int describes computations that yield integers, and in order to get to the Int you need to run the computation. if you have a pure function f and want to feed it with random values, you need to do something like: randomIO = \ x - randomIO = \ y - return (f x y) the complete expression has type IO Int again. don't try to strip off that IO; there are ways, but they don't teach you how to do it right. hth, m. signature.asc Description: Digital signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Error building Edison 1.2.0.1
Hi Rob, I've built Edison 1.2.0.1 using ghc-6.6. (I'm testing the macports, formerly darwinports, packages for the new 6.6 release.) The build goes fine, but the ./Setup register fails claiming that the directory /opt/local/lib/EdisonAPI-1.2/ghc-6.6/include does not exist. I can make the directory by hand, and the registration works. I have an ugly workaround, but I wanted to check with you that this is really a cabal bug. Installation using ghc-6.4.2 on OS X/ppc worked just fine for me. Best Wishes, Greg ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Newbie and working with IO Int and Int
Hi, What's wrong with doing it this way? -- ** UNTESTED CODE ** verifyAdd :: Int -gt; Int -gt; Int -gt; Bool verifyAdd a b sum | a + b == sum = True otherwise= False testAddMundane :: Int -gt; Int -gt; Bool testAddMundane a b = verifyAdd a b (a + b) -- all the IO-dependent stuff is below this line -- testAddRandom :: IO Bool testAddRandom = do a lt;- randomIO b lt;- randomIO return verifyAdd a b (a + b) First thanks, but the problem is that I can't check if testAddRandom was sucessfull or not. If I replace (a+b) with (a+b-1) it still executes but couldn't check if it's True or False :-P -- Víctor A. Rodríguez (http://www.bit-man.com.ar) El bit Fantasma (Bit-Man) Perl Mongers Capital Federal (http://cafe.pm.org/) GNU/Linux User Group - FCEyN - UBA (http://glugcen.dc.uba.ar/) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Error building Edison 1.2.0.1
On Oct 17, 2006, at 12:55 PM, Gregory Wright wrote: Hi Rob, I've built Edison 1.2.0.1 using ghc-6.6. (I'm testing the macports, formerly darwinports, packages for the new 6.6 release.) The build goes fine, but the ./Setup register fails claiming that the directory /opt/local/lib/EdisonAPI-1.2/ghc-6.6/include does not exist. I can make the directory by hand, and the registration works. I have an ugly workaround, but I wanted to check with you that this is really a cabal bug. Installation using ghc-6.4.2 on OS X/ppc worked just fine for me. Best Wishes, Greg I'm not doing anything unusual with the cabal scripts (that I'm aware of!), so I expect this is a cabal or GHC bug. BTW, could you run the test suite if you get a moment? Every data point helps. Rob Dockins Speak softly and drive a Sherman tank. Laugh hard; it's a long way to the bank. -- TMBG ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Newbie and working with IO Int and Int
What's wrong with doing it this way? -- ** UNTESTED CODE ** verifyAdd :: Int -gt; Int -gt; Int -gt; Bool verifyAdd a b sum | a + b == sum = True otherwise = False testAddMundane :: Int -gt; Int -gt; Bool testAddMundane a b = verifyAdd a b (a + b) -- all the IO-dependent stuff is below this line -- testAddRandom :: IO Bool testAddRandom = do a lt;- randomIO b lt;- randomIO return verifyAdd a b (a + b) I discovered something worst yet :-P Using the next code and calling verifyAdd or testAddMundane it says : Program error: verifyAdd: ERROR Instead calling testAddRandom only says : :: IO Bool (55 reductions, 92 cells) CODE STARTS HERE, AND IS TESTED - import Random verifyAdd :: Int - Int - Int - Bool verifyAdd a b sum = error verifyAdd: ERROR testAddMundane :: Int - Int - Bool testAddMundane a b = verifyAdd a b (a + b) -- all the IO-dependent stuff is below this line -- testAddRandom :: IO Bool testAddRandom = do a - randomIO b - randomIO return ( verifyAdd a b (a+b) ) -- Víctor A. Rodríguez (http://www.bit-man.com.ar) El bit Fantasma (Bit-Man) Perl Mongers Capital Federal (http://cafe.pm.org/) GNU/Linux User Group - FCEyN - UBA (http://glugcen.dc.uba.ar/) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Newbie and working with IO Int and Int
On Oct 17, 2006, at 1:37 PM, Víctor A. Rodríguez wrote: What's wrong with doing it this way? -- ** UNTESTED CODE ** verifyAdd :: Int -gt; Int -gt; Int -gt; Bool verifyAdd a b sum | a + b == sum = True otherwise = False testAddMundane :: Int -gt; Int -gt; Bool testAddMundane a b = verifyAdd a b (a + b) -- all the IO-dependent stuff is below this line -- testAddRandom :: IO Bool testAddRandom = do a lt;- randomIO b lt;- randomIO return verifyAdd a b (a + b) I discovered something worst yet :-P Using the next code and calling verifyAdd or testAddMundane it says : Program error: verifyAdd: ERROR Instead calling testAddRandom only says : :: IO Bool (55 reductions, 92 cells) This is due to the magic of lazy evaluation. You never use the result of 'testAddRandom', so it's never evaluated, which means your call to 'error' is also never evaluated. Type: testAddRandom = print on the command line and you should get the same error, because the call to 'print' demands the result of running testAddRandom. CODE STARTS HERE, AND IS TESTED - import Random verifyAdd :: Int - Int - Int - Bool verifyAdd a b sum = error verifyAdd: ERROR testAddMundane :: Int - Int - Bool testAddMundane a b = verifyAdd a b (a + b) -- all the IO-dependent stuff is below this line -- testAddRandom :: IO Bool testAddRandom = do a - randomIO b - randomIO return ( verifyAdd a b (a+b) ) -- Víctor A. Rodríguez (http://www.bit-man.com.ar) El bit Fantasma (Bit-Man) Perl Mongers Capital Federal (http://cafe.pm.org/) GNU/Linux User Group - FCEyN - UBA (http://glugcen.dc.uba.ar/) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe Rob Dockins Speak softly and drive a Sherman tank. Laugh hard; it's a long way to the bank. -- TMBG ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Error building Edison 1.2.0.1
On Oct 17, 2006, at 1:07 PM, Robert Dockins wrote: On Oct 17, 2006, at 12:55 PM, Gregory Wright wrote: Hi Rob, I've built Edison 1.2.0.1 using ghc-6.6. (I'm testing the macports, formerly darwinports, packages for the new 6.6 release.) The build goes fine, but the ./Setup register fails claiming that the directory /opt/local/lib/EdisonAPI-1.2/ghc-6.6/include does not exist. I can make the directory by hand, and the registration works. I have an ugly workaround, but I wanted to check with you that this is really a cabal bug. Installation using ghc-6.4.2 on OS X/ppc worked just fine for me. Best Wishes, Greg I'm not doing anything unusual with the cabal scripts (that I'm aware of!), so I expect this is a cabal or GHC bug. BTW, could you run the test suite if you get a moment? Every data point helps. Hi Rob, OK, it looks like cabal has gone slightly broken again. :-( Here's the test data: OS X 10.4.8/ppc PowerBook G4, 1.5 GHz, 1 GB ram ghc-6.6, cabal 1.1.6 as distributed with ghc-6.6, built using macports test output: Welcome to Darwin! crossroads-able cd ~/Desktop/edison-1.2.0.1-source/test/ crossroads-able ./dist/build/testSuite/testSuite Cases: 1728 Tried: 1728 Errors: 0 Failures: 0 crossroads-able Everything looks good but for the package registration. I should add that I find the Edison package wonderfully easy to work with. It has really helped me out while writing simulation of the custom communication system for a customer. Many thanks to you, Rob, and Chris Okasaki for this fine software! Best Wishes, Greg Rob Dockins Speak softly and drive a Sherman tank. Laugh hard; it's a long way to the bank. -- TMBG ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Newbie and working with IO Int and Int
Am Dienstag, 17. Oktober 2006 19:37 schrieb Víctor A. Rodríguez: What's wrong with doing it this way? -- ** UNTESTED CODE ** verifyAdd :: Int -gt; Int -gt; Int -gt; Bool verifyAdd a b sum | a + b == sum = True otherwise = False testAddMundane :: Int -gt; Int -gt; Bool testAddMundane a b = verifyAdd a b (a + b) -- all the IO-dependent stuff is below this line -- testAddRandom :: IO Bool testAddRandom = do a lt;- randomIO b lt;- randomIO return verifyAdd a b (a + b) I discovered something worst yet :-P Using the next code and calling verifyAdd or testAddMundane it says : Program error: verifyAdd: ERROR Instead calling testAddRandom only says : :: IO Bool (55 reductions, 92 cells) Well, that's absolutely correct. 'return (error ERROR)' is different from 'error ERROR' and is a perfectly well-behaved monadic value. As long as you don't try to evaluate the returned value (e.g. for printing it), it doesn't trigger the error (remember, Haskell is lazy!). And by default, hugs doesn't print the results of IO-actions: Hugs putStrLn No result No result Hugs :set +I Hugs putStrLn No result No result () - this is the result of the IO-action putStrLn No Result The option +I says you want the results of IO-actions to be printed, and indeed: Verify :set +I Verify testAddRandom Program error: verifyAdd: ERROR The same, if we explicitly ask for the result to be printed if the +I option isn't set: Verify testAddRandom = print Program error: verifyAdd: ERROR ghci-6.6 does so by default (for some IO-actions, not for e.g. putStrLn ..): *Verify testAddRandom *** Exception: verifyAdd: ERROR Prelude System.CPUTime t - getCPUTime 1300 and ghci-6.4.2 like hugs needs to be asked for the result of the IO-action *Verify r - testAddRandom *Verify r *** Exception: verifyAdd: ERROR *Verify testAddRandom *Verify it *** Exception: verifyAdd: ERROR Now let's use the result of testAddRandom: testAnew :: IO () testAnew = do b - testAddRandom print (True || b) print (False b) print b b is bound to the result of testAddRandom, i.e. error verifyAdd: ERROR, but it is not evaluated until needed, so True and False get printed before the exception is raised when we ask for it to be printed. *Verify testAnew True False *** Exception: verifyAdd: ERROR HTH, Daniel CODE STARTS HERE, AND IS TESTED - import Random verifyAdd :: Int - Int - Int - Bool verifyAdd a b sum = error verifyAdd: ERROR testAddMundane :: Int - Int - Bool testAddMundane a b = verifyAdd a b (a + b) -- all the IO-dependent stuff is below this line -- testAddRandom :: IO Bool testAddRandom = do a - randomIO b - randomIO return ( verifyAdd a b (a+b) ) -- Víctor A. Rodríguez (http://www.bit-man.com.ar) El bit Fantasma (Bit-Man) Perl Mongers Capital Federal (http://cafe.pm.org/) GNU/Linux User Group - FCEyN - UBA (http://glugcen.dc.uba.ar/) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] 6.4 - 6.6, scoped type variables, prescribing poly-/mono-morphism
I've been writing some code that relies heavily on the type system. Some of my polymorphic functions end up too polymorphic. I'm looking for some tips and references regarding prescribing poly-/mono-morphism. I know of three ways to do it: 1) rely on the monomorphism-restriction -- kind of scary in that its not explicitly obvious 2) introducing scoped-type variables of interest -- explicit and modular 3) introducing all type variables with a forall -- explicit but not modular The rest of this email is a discussion of a particular problem I'm having. Scoped-type variables worked in 6.4, but no longer in 6.6. I'm sure there's good reasons for this (I think I found a Peyton-Jones message regarding it in 6.4-6.5) I just didn't quite catch on to them. The problem is in the |bop| function: class SubType a v where -- the lack of fundeps is required by design inj :: a - v lazyPrj :: v - Maybe a bop :: forall x y z m c v . ( SubType x v, SubType y v, SubType z v , SubType (Fun m c v) v , Monad m, Comonad c ) = (x - y - z) - Fun m c v bop op = Fun fn where fn = wrap fn' where fn' v0 = (inj . Fun) (wrap fn'') where fn'' v1 = inj (lazyPrj v0 `op` lazyPrj v1) wrap :: (v - v) - (c v - m v) wrap = (return .) . (. counit) The explicit forall is needed to introduce the scoped type variables so that I can prescribe the type of |wrap|. After that, the monomorphism restriction on |wrap| takes care of the rest of my worries (that there is only one |m|, only one |c|, and only one |v|). If I leave the types to inference (i.e. drop the forall and the type ascription for |wrap|), then I end up with this type bop :: ( SubType x v2, SubType y v1, SubType z v1 , SubType (Fun m c v1) v2 , Monad m, Comonad c ) = (x - y - z) - Fun m c v2 Note the multiple |v|s; they wreak havoc in the rest of my code. (The monomorphism restriction still takes care of the |m| and |c|.) I'd like to not have to introduce the forall, because with that comes introducing the entire context of the type. Thus I have to maintain any changes to the context, which I would prefer to leave to inference for modularity's sake. In 6.4 I was able to fix this without having to introduce the forall; I could introduce scoped type-variables in patterns to get the job done. That felt a bit like voodoo, especially when trying to get it right for 6.6--which I gave up on doing. I can post the code that works with 6.4 if anyone would like to see it (I just can't find it at the moment). I know there's some work on introducing partial signatures (fun pat | False = ...), but I don't see how to prescribe monomorphism for particular type variables in that way. Any thoughts on how to get the preferred signature using scoped-type variables in 6.6? I'd also welcome any references you might think are relevant. Thanks for your time, Nick ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Type level functions (type of decreasing list)
I'm wondering about creating a data structure that has the type of decreasing numbers. If I want an increasing list, it is easy... {-# OPTIONS -fglasgow-exts #-} data Succ a = S a deriving Show data Zero = Z deriving Show data Seq' a = Cons' a (Seq' (Succ a)) | Nil' deriving Show ...which can be used like... zero = Z one = S zero two = S one three = S two increasing = Cons' zero (Cons' one (Cons' two (Cons' three Nil'))) ...on the other hand, if I want the decreasing list, I can try... class Pre a b | a - b instance Pre (Succ a) a instance Pre Zero Zero data (Pre a b) = Seq a = Cons a (Seq b) | Nil decreasing = Cons three (Cons two (Cons one Nil)) ...but that complains about Not in scope: type variable `b'. Of course that makes perfect sense, but I'd like to know if there is a Haskell idiom that I'm missing in order to get this to work. Thanks, Greg Buchholz ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Type level functions (type of decreasing list)
Here's an attempt with GADTs: \begin{code} {-# OPTIONS_GHC -fglasgow-exts #-} data Succ a data Zero data Seq a b where Cons :: a - Seq a b - Seq a (Succ b) Nil :: Seq a Zero \end{code} Seems to work for me. Spencer Janssen On Oct 17, 2006, at 6:37 PM, Greg Buchholz wrote: I'm wondering about creating a data structure that has the type of decreasing numbers. If I want an increasing list, it is easy... {-# OPTIONS -fglasgow-exts #-} data Succ a = S a deriving Show data Zero = Z deriving Show data Seq' a = Cons' a (Seq' (Succ a)) | Nil' deriving Show ...which can be used like... zero = Z one = S zero two = S one three = S two increasing = Cons' zero (Cons' one (Cons' two (Cons' three Nil'))) ...on the other hand, if I want the decreasing list, I can try... class Pre a b | a - b instance Pre (Succ a) a instance Pre Zero Zero data (Pre a b) = Seq a = Cons a (Seq b) | Nil decreasing = Cons three (Cons two (Cons one Nil)) ...but that complains about Not in scope: type variable `b'. Of course that makes perfect sense, but I'd like to know if there is a Haskell idiom that I'm missing in order to get this to work. Thanks, Greg Buchholz ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Type level functions (type of decreasing list)
Spencer Janssen wrote: ] Here's an attempt with GADTs: ] ] \begin{code} ] {-# OPTIONS_GHC -fglasgow-exts #-} ] data Succ a ] data Zero ] data Seq a b where ] Cons :: a - Seq a b - Seq a (Succ b) ] Nil :: Seq a Zero ] \end{code} ] ] Seems to work for me. Hmm. Maybe I'm missing something. With the program below I get the following error message (with ghci 6.6)... Couldn't match expected type `Succ Zero' against inferred type `Zero' Expected type: Succ (Succ (Succ Zero)) Inferred type: Succ (Succ Zero) In the first argument of `Cons', namely `two' In the second argument of `Cons', namely `(Cons two (Cons one Nil))' {-# OPTIONS -fglasgow-exts #-} data Succ a = S a deriving Show data Zero = Z deriving Show zero = Z one = S zero two = S one three = S two data Seq a b where Cons :: a - Seq a b - Seq a (Succ b) Nil :: Seq a Zero decreasing = Cons three (Cons two (Cons one Nil)) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: optimization help
Hello, Good, writeCSV writes out every row immediately after it got it. I eliminated (++ [nl]) in the hope of reducing the constant factor slightly. Using difference lists for that is nicer but here you go. I'm not sure how you'd use difference lists here. Also, for some reason GHC runs slightly slower (compiled with -O) using sequencing instead of ++; the version with consistently (a very unrigorous consistence) takes between 5 and 8 seconds longer than the version with ++ (when filtering out some columns from every row and writing the new file). Is there some hidden cost in switching from the mapM_ to a direct sequence? Concerning select, one myFilter can be fused away and there is the transpose trick for filtering out the columns: columns get filtered once and for all and (map (`elem` tags)) only needs to be computed once. I don't know why the MonadReader is necessary, so I removed it You're right, no need for myFilter on the rows. I used the Reader because at first I thought it would make a nicer interface (I have since changed my mind about that) and it didn't seem to hurt performance. I think using transpose requires more work (and is slower) than filtering each row, particularly if the mask (map (`elem` tags)) is only computed once (shouldn't the compiler do that automatically since the expression is constant?). Transpose requires passing over the entire structure at least once (possibly more depending on how clever the compiler is); so that is a minimum of two complete passes over the structure just to transpose and untranspose. Filtering each row is just one pass over the structure (doing very little work assuming the mask is computed once). My (still very unrigorous) performance tests seem to bear this out where the transposed version consistently takes a few seconds longer. I hope so... Though the 13 seconds are disproportionally high (only 22000 rows to be written) compared to 90 seconds (75 rows to be written). Yes, that does seem suspicious. Perhaps the cost of the testing the filter on each row accounts for this? I've attached my current fastest code if you, or anybody, is interested in taking a shot at tightening it further (or just interested in lightweight CSV-like processing). thanks, Jeff -- readCSV file = do v - B.readFile file return $ map (mySplit ',') $ B.lines v writeCSV file tbl = do h - openFile file WriteMode let writeRow = mapM_ (B.hPut h) . (++ [nl]) . intersperse comma mapM_ writeRow tbl hClose h where comma = B.singleton ',' nl = B.singleton '\n' select targs test (cols : rows) = map narrow (cols : filter (test cols) rows) where narrow = map snd . filter fst . zip mask mask = map (`elem` targs) cols col x cols row = row !! i where Just i = lookup x $ zip cols [0..] {-- A slightly smarter ByteString split to deal with quotes and remove whitespace. This could be optimized somewhat (e.g. folding killspace into mySplit) but the current performance seems to be as good as ByteString.split-- i.e. using ByteString.split versus mySplit doesn't affect running time. --} mySplit c bs = go False 0 bs where go isQuote i xs | i = B.length xs = [killSpace xs] | isQuote x0 == '\\' = go True (i+2) xs | x0 == '' = go (not isQuote) (i+1) xs | not isQuote x0 == c = killSpace x' : go False 0 (B.tail xs') | otherwise = go isQuote (i+1) xs where x0 = B.index xs i (x',xs') = B.splitAt i xs killSpace = B.dropWhile isSpace . dropEndWhile isSpace dropEndWhile test x | B.null x = x | otherwise = if test $ B.last x then dropEndWhile test $ B.init x else x ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe