Re: [Haskell-cafe] is closing a class this easy?
What is it for? Yes, you would know that only A and B are Public, but you have no way of telling that to the compiler. I usually prefer something like that: class Public x where blah :: ... isAB :: forall y. (A - y) - (B - y) - x - y Both solutions, however, allow the user to declare some new instances when GeneralizedNewtypeDeriving is enabled. On 17 Jul 2009, at 19:38, Conor McBride wrote: Friends Is closing a class this easy? -- module Moo ( Public(..) ) where class Private x = Public x where blah :: ... class Private x where instance Private A where instance Public A where blah = ... instance Private B where instance Public B where blah = ... -- Modules importing Moo get Public and its instances, but cannot add new ones: any such instances must be accompanied by Private instances, and Private is out of scope. Does this work? If not, why not? If so, is this well known? It seems to be just what I need for a job I have in mind. I want a class with nothing but hypothetical instances. It seems like I could write -- module Noo ( Public(..) , public ) where class Private x = Public x where blah :: ... blah = ... class Private x where public :: (forall x. Public x = x - y) - y public f = f Pike data Pike = Pike instance Private Pike instance Public Pike -- But if I don't tell 'em Pike, I've ensured that blah can only be used in the argument to public. Or is there a hole? Cures youriously Conor ___ 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] is closing a class this easy?
Oops... Sorry, wrong line. Should be isAB :: forall p. p A - p B - p x On 18 Jul 2009, at 10:51, Miguel Mitrofanov wrote: What is it for? Yes, you would know that only A and B are Public, but you have no way of telling that to the compiler. I usually prefer something like that: class Public x where blah :: ... isAB :: forall y. (A - y) - (B - y) - x - y Both solutions, however, allow the user to declare some new instances when GeneralizedNewtypeDeriving is enabled. On 17 Jul 2009, at 19:38, Conor McBride wrote: Friends Is closing a class this easy? -- module Moo ( Public(..) ) where class Private x = Public x where blah :: ... class Private x where instance Private A where instance Public A where blah = ... instance Private B where instance Public B where blah = ... -- Modules importing Moo get Public and its instances, but cannot add new ones: any such instances must be accompanied by Private instances, and Private is out of scope. Does this work? If not, why not? If so, is this well known? It seems to be just what I need for a job I have in mind. I want a class with nothing but hypothetical instances. It seems like I could write -- module Noo ( Public(..) , public ) where class Private x = Public x where blah :: ... blah = ... class Private x where public :: (forall x. Public x = x - y) - y public f = f Pike data Pike = Pike instance Private Pike instance Public Pike -- But if I don't tell 'em Pike, I've ensured that blah can only be used in the argument to public. Or is there a hole? Cures youriously Conor ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Importance of identity element in finger trees?
Hi all, I was looking at finger trees and the tricks for getting priority queues out of them seemed a little hackish, with a distinguished infinity element or maxBound. But it seems (although I have not yet tried it) like in many cases the monoid's identity element wouldn't be necessary (a bit like the difference between fold* and fold*1). Could a finger tree be applied to an arbitrary semigroup? Or is the identity more fundamental than it looks? Thanks, Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] is closing a class this easy?
Hi Miguel On 18 Jul 2009, at 07:58, Miguel Mitrofanov wrote: Oops... Sorry, wrong line. Should be isAB :: forall p. p A - p B - p x Yep, dependent case analysis, the stuff of my thesis,... On 18 Jul 2009, at 10:51, Miguel Mitrofanov wrote: What is it for? I have a different purpose in mind. I want to write localize :: (forall a. Equipment a = Abstract a) - Concrete rather than localize :: (forall a. F1 a - ... - Fn a - Abstract a) - Concrete so I can use the type class machinery to pass around the dictionaries of equipment. I want to make sure that nobody else gets the equipment. It's possible that I don't need to be so extreme: it's enough that there's no other way to use Abstracts than via localize. Yes, you would know that only A and B are Public, but you have no way of telling that to the compiler. I usually prefer something like that: class Public x where blah :: ... isAB :: forall y. (A - y) - (B - y) - x - y But now I can write bogus instances of Public with genuine implementations of blah and wicked lies for isAB. It is important to use the dependent version, otherwise I might have instance Public (A, B) where isAB af bf (a, b) = af a and lots more, without even lying. Both solutions, however, allow the user to declare some new instances when GeneralizedNewtypeDeriving is enabled. I'm scared. What about this? data EQ :: * - * - * where Refl :: EQ x x class Public x where blah :: EQ x Fred instance Public Fred where blah = Refl What happens when I say newtype Jim = Hide Fred deriving Public ? I tried it. I get blah :: EQ Jim Fred It's clear that GeneralizedNewtypeDeriving goes too far. I hope a class with *no* instances in public has no newtype leak! Fun stuff. Cheers Conor ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] is closing a class this easy?
Conor, I'm scared. What about this? data EQ :: * - * - * where Refl :: EQ x x class Public x where blah :: EQ x Fred instance Public Fred where blah = Refl What happens when I say newtype Jim = Hide Fred deriving Public ? I tried it. I get blah :: EQ Jim Fred It's clear that GeneralizedNewtypeDeriving goes too far. Now, I am scared. This should be regarded as a bug in generalised newtype deriving, shouldn't it? I would expect newtype deriving to be unable to come up with instances that cannot be written by hand. I would have expected people out on the streets marching to GHC headquarters by now; how can you stay so calm? Cheers, Stefan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] is closing a class this easy?
On 18 Jul 2009, at 01:43, Lennart Augustsson wrote: As far as I know it works. It's an old Oleg trick. Then it probably does work. The only drawback is that error messages may refer to Private. As I found out when probing its security. No instance for Moo.Private shows up. I guess that's what happens when you hide stuff: you get told what stuff's being hidden. In some situations, that's insecure, but here it's ok. Cheers (and have fun in China, Lennart!) Conor ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Debugging methods for haskell
Henning Thielemann lemm...@henning-thielemann.de writes: On Thu, 16 Jul 2009, Fernan Bolando wrote: Hi all I recently used 2 hours of work looking for a bug that was causing Program error: Prelude.!!: index too large A good way to avoid such problems is to avoid partial functions at all. (!!) is also inefficient. Is it possible to define the function in terms of foldl? I've looked at the code a bit more, and, with apologies to the original poster, it doesn't look much like Haskell. For example, in http://plan9.bell-labs.com/sources/contrib/fernan/escomma/Circuit.hs there's stuff beginning with tADM :: Int tADM = 1 tVSRC :: Int tVSRC = 2 tISRC :: Int tISRC = 3 ... that I think probably should be data Something = ADM | VSRC | ISRC ... deriving (Enum, ...) though when I get to (((fst z0)!!pMSET)!!pMTYPE) == mOP I'm at a loss to determine quite what the intention is. Maybe it should be an array indexed by enum types, maybe a function, maybe something that can be pattern matched on? I don't know. -- Jón Fairbairn jon.fairba...@cl.cam.ac.uk ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Plot data reconstruction reading pixel colors from image files
Henning Thielemann wrote: Felipe Lessa schrieb: On Fri, Jul 17, 2009 at 06:31:20PM +0200, Cetin Sert wrote: How can I open and read colors of specific pixels of an image file in Haskell? Which packages, functions do you recommend? You could try DevIL, SDL-image or Gtk, I guess. Perhaps http://hackage.haskell.org/package/pgm This is (one of) the problems that AC-EasyRaster is supposed to make easy. (AC-EasyRaster is just is a convinience binding over the top of Gtk2hs... Makes it easier to find the stuff you're actually looking for. Hopefully.) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] cabal version issue
Hello, vigalc...@ubuntu:~/FTP/Haskell/06052009.Swish-0.2.1$ cabal --version cabal-install version 0.5.1 using version 1.4.0.1 of the Cabal library vigalc...@ubuntu:~/FTP/Haskell/Swish-0.2.1$ cabal configure --user --prefix=$HOME Warning: swish.cabal: A package using section syntax should require Cabal-Version: = 1.2 or equivalent. Warning: swish.cabal: A package using section syntax should require Cabal-Version: = 1.2 or equivalent. What is the Cabal-Version in the latter? Why I am getting this warning? Thanks, Vasili ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANN: AC-Vector, AC-Colour and AC-EasyRaster-GTK
Am Samstag, 18. Juli 2009 06:31 schrieben Sie: On Jul 18, 2009, at 2:35 AM, Wolfgang Jeltsch wrote: So I should upload a package with German identifiers to Hackage? Sure, why not? The fact that I can't read it is my loss, not your fault, and there will be plenty of other German-reading Haskellers to benefit from it. I've happily worked with programs in French (not large ones (:-)). I don’t think, it’s a good idea to have German identifiers, since Haskell’s keywords are English. On the other hand, I strongly argue that a library about Bézier curves uses the identifier Bézier, not Bezier. So non-ASCII identifiers are useful even if identifiers are in English. Best wishes, Wolfgang ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] catchSTM and asynchronous exceptions
I couldn't find any information on whether catchSTM catches asynchronous exceptions so I tried to run the following: import Control.Concurrent.STM import Control.Concurrent import Control.Exception import Prelude hiding (catch) test = do tid - myThreadId forkIO (threadDelay 500 throwTo tid (AssertionFailed Exception in forked thread!)) (atomically $ retry `catchSTM` stmHandler) `catch` (ioHandler tid) where stmHandler (e::SomeException) = throw $ AssertionFailed (Caught Exc. in STM; Rethrowing exception: ++ show e) ioHandler tid (e::SomeException) = print (tid,Caught Exception in IO: ,e) Yielding the following output: # (ThreadId 6942,Caught Exception in IO: ,Exception in forked thread!) Apparently the exception is caught by catch and not by catchSTM. So the point is that catchSTM is only meant to be used for non-async exceptions, right? Regards, Peter ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
newtype deriving, was Re: [Haskell-cafe] is closing a class this easy?
Hi Stefan On 18 Jul 2009, at 09:42, Stefan Holdermans wrote: Conor, What happens when I say newtype Jim = Hide Fred deriving Public ? I tried it. I get blah :: EQ Jim Fred It's clear that GeneralizedNewtypeDeriving goes too far. Now, I am scared. This should be regarded as a bug in generalised newtype deriving, shouldn't it? I would expect newtype deriving to be unable to come up with instances that cannot be written by hand. I think the latter is a useful general principle for deriving. The trouble here is that somewhere along the line (GADTs? earlier?) it became possible to construct candidates for p :: * - * which don't respect isomorphism. These tend to be somewhat intensional in nature, and they mess up the transfer of functionality. If we could be sure that all such a p would do with its parameter (x, say) is trade in values of x (as opposed to trading in the identity of x), then we could be sure that p respects isomorphisms. I'm hoping that a category theorist will say something about dinaturality at this point, because I'd like to understand that stuff. I wonder if there's a potential refinement of the kind system lurking here, distinguishing *, types-up-to-iso, from |*|, types-up-to-identity. That might help us to detect classes for which newtype deriving is inappropriate: GADTs get indexed over |*|, not *; classes of *s are derivable, but classes of |*|s are not. I certainly don't have a clear proposal just now. It looks like an important distinction: recognizing it somehow might buy us something. I would have expected people out on the streets marching to GHC headquarters by now; how can you stay so calm? GHC HQ are up to their armpits in newtypes already. This distinction between type equality and (trivial) type isomorphism is something they're already facing. I don't know if they've solved this problem yet, but I suspect they're in the area. No need for a commotion. All the best Conor ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] can there be (hash-table using) O(n) version of this (I think currently) n log n algo?
However you can use the wider idea of hashing: A nesting of two finite maps. One fast, but approximative map. And one slow, but exact map. The quintessential example is an array indexed with some hash function for the first map. And linked lists of (key,value) pairs as the latter. In Haskell you might want to use IntMap and a the mentioned list of pairs (combined with the lookup functions from Data.List). Of course you need to supply a function to hash your keys to Int for the IntMap. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Importance of identity element in finger trees?
On Sat, Jul 18, 2009 at 03:57:12AM -0400, Daniel Peebles wrote: I was looking at finger trees and the tricks for getting priority queues out of them seemed a little hackish, with a distinguished infinity element or maxBound. But it seems (although I have not yet tried it) like in many cases the monoid's identity element wouldn't be necessary (a bit like the difference between fold* and fold*1). Could a finger tree be applied to an arbitrary semigroup? Or is the identity more fundamental than it looks? Two answers: 1) It can be applied to an arbitrary semigroup, because you can always turn that into a monoid by adding an identity element. 2) It suffices to have an associative operation with a left identity (exercise 7 in the paper). But an identity is still needed, as the measure of the empty tree. You could special case that, but it would be equivalent to 1) above. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] can there be (hash-table using) O(n) version of this (I think currently) n log n algo?
Hello Thomas, Saturday, July 18, 2009, 2:24:21 AM, you wrote: Further, is there a hashtable implementation for haskell that doesn't live in IO? Maybe in ST or something? import Prelude hiding (lookup) import qualified Data.HashTable import Data.Array import qualified Data.List as List data HT a b = HT (a-Int) (Array Int [(a,b)]) -- size is the size of array (we implement a closed hash) -- hash is the hash function (a-Int) -- list is assoclist of items to put in hash create size hash list = HT hashfunc (accumArray (flip (:)) [] (0, arrsize-1) (map (\(a,b) - (hashfunc a,(a,b))) list) ) where arrsize = head$ filter (size)$ iterate (\x-3*x+1) 1 hashfunc a = hash a `mod` arrsize lookup a (HT hash arr) = List.lookup a (arr!hash a) main = do let assoclist = [(one, 1), (two, 2), (three, 3)] hash = create 10 (fromEnum . Data.HashTable.hashString) assoclist print (lookup one hash) print (lookup zero hash) -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANN: AC-Vector, AC-Colour and AC-EasyRaster-GTK
On 18 Jul 2009, at 13:26, Wolfgang Jeltsch wrote: Am Samstag, 18. Juli 2009 06:31 schrieben Sie: On Jul 18, 2009, at 2:35 AM, Wolfgang Jeltsch wrote: So I should upload a package with German identifiers to Hackage? Sure, why not? The fact that I can't read it is my loss, not your fault, and there will be plenty of other German-reading Haskellers to benefit from it. I've happily worked with programs in French (not large ones (:-)). I don’t think, it’s a good idea to have German identifiers, since Haskell’s keywords are English. On the other hand, I strongly argue that a library about Bézier curves uses the identifier Bézier, not Bezier. So non- ASCII identifiers are useful even if identifiers are in English.\ And I think that a library about Dynkin diagrams should use the identifier Dynkin, not Дынкин.___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] cabal version issue
The message means that the .cabal file should contain the line Cabal- Version: = 1.2 Sjoerd On Jul 18, 2009, at 11:17 AM, Vasili I. Galchin wrote: Hello, vigalc...@ubuntu:~/FTP/Haskell/06052009.Swish-0.2.1$ cabal --version cabal-install version 0.5.1 using version 1.4.0.1 of the Cabal library vigalc...@ubuntu:~/FTP/Haskell/Swish-0.2.1$ cabal configure --user -- prefix=$HOME Warning: swish.cabal: A package using section syntax should require Cabal-Version: = 1.2 or equivalent. Warning: swish.cabal: A package using section syntax should require Cabal-Version: = 1.2 or equivalent. What is the Cabal-Version in the latter? Why I am getting this warning? Thanks, Vasili ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Sjoerd Visscher sjo...@w3future.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: newtype deriving, was Re: [Haskell-cafe] is closing a class this easy?
Conor, What happens when I say newtype Jim = Hide Fred deriving Public ? I tried it. I get blah :: EQ Jim Fred Thinking of it; this *does* make sense in System FC. The newtype- declaration gives you as an axiom Hide :: Jim ~ Fred To give an instance of Public for Jim, we have to provide blah :: EQ Jim Fred which, with Refl :: forall (a :: *) (b :: *). (a ~ b) = EQ a b can be given straightforwardly as blah = Refl {Jim, Fred, Hide} So, the problem, if any, is that the System FC-encoding of newtypes renders them into guarded type equalities, rather than proper type isomorphisms. (Or, the other way around, reduces ~ to type isomorphism rather than type equality.) I wonder if there's a potential refinement of the kind system lurking here, distinguishing *, types-up-to-iso, from |*|, types-up-to- identity. That might help us to detect classes for which newtype deriving is inappropriate: GADTs get indexed over |*|, not *; classes of *s are derivable, but classes of |*|s are not. I certainly don't have a clear proposal just now. It looks like an important distinction: recognizing it somehow might buy us something. That seems a promising approach. We would then have Jim :: * Fred :: * EQ :: |*| - |*| - * Hide :: Jim ~ Fred Refl :: forall (a :: |*|) (b :: |*|). (a ~ b) = EQ a b and (I guess) a type-level operation that allows you to lift every type T :: * into |T| :: |*|. Then we have, blahFred = Refl {|Fred|, |Fred|, |Fred|} which make sense, given that |*| :: TY, but both blahJim = Refl {Jim, Fred, Hide} and blahJim' = Refl {|Jim|, |Fred|, Hide} and variations thereof would be ill-kinded, as desired. And, indeed, generalised newtype deriving should then only make sense for *-indexed classes. I think this would work. Cheers, Stefan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: newtype deriving, was Re: [Haskell-cafe] is closing a class this easy?
Am Samstag, 18. Juli 2009 11:43 schrieb Conor McBride: The trouble here is that somewhere along the line (GADTs? earlier?) it became possible to construct candidates for p :: * - * which don't respect isomorphism. Hello Conor, I’m not sure whether I exactly understand what you mean here. I think, it’s the following: Say, you have a type A and define a type B as follows: newtype B = B A Then, for any p :: * - *, the type p A should be isomorphic to p B, i.e., it should basically contain the same values. This is no longer true with GADTs since you can define something like this: data GADT a where GADT :: GADT A Now, GADT :: GADT A but not GADT :: GADT B. Is this what you mean? These tend to be somewhat intensional in nature, and they mess up the transfer of functionality. Could you maybe elaborate on this? Best wishes, Wolfgang ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] is closing a class this easy?
On Fri, Jul 17, 2009 at 4:38 PM, Conor McBrideco...@strictlypositive.org wrote: class Private x where public :: (forall x. Public x = x - y) - y public f = f Pike data Pike = Pike instance Private Pike instance Public Pike -- But if I don't tell 'em Pike, I've ensured that blah can only be used in the argument to public. Well I appreciated this bit even if no-one else did! :-) Also, that's a nifty trick if it works! D ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] is closing a class this easy?
Am Samstag, 18. Juli 2009 08:58 schrieb Miguel Mitrofanov: Oops... Sorry, wrong line. Should be isAB :: forall p. p A - p B - p x Is this a well-known approach for closing classes? I came across the same idea and implemented a generic framework for closing classes in this way. I did this to simulate algebraic data kinds and kind polymorphism over such kinds. I needed this for the record system of Grapefruit. The code is here: http://code.haskell.org/grapefruit/main/grapefruit-records/src/ Explaination of the techniques used in this code will probably follow as part of an IFL 2009 paper. Now I wonder which of my ideas are actually new and which are just old hat. Could you maybe answer this question? Best wishes, Wolfgang ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging methods for haskell
On Sat, Jul 18, 2009 at 4:57 PM, Jon Fairbairnjon.fairba...@cl.cam.ac.uk wrote: Henning Thielemann lemm...@henning-thielemann.de writes: On Thu, 16 Jul 2009, Fernan Bolando wrote: Hi all I recently used 2 hours of work looking for a bug that was causing Program error: Prelude.!!: index too large A good way to avoid such problems is to avoid partial functions at all. (!!) is also inefficient. Is it possible to define the function in terms of foldl? I've looked at the code a bit more, and, with apologies to the original poster, it doesn't look much like Haskell. For example, in http://plan9.bell-labs.com/sources/contrib/fernan/escomma/Circuit.hs there's stuff beginning with tADM :: Int tADM = 1 tVSRC :: Int tVSRC = 2 tISRC :: Int tISRC = 3 ... that I think probably should be data Something = ADM | VSRC | ISRC ... deriving (Enum, ...) though when I get to (((fst z0)!!pMSET)!!pMTYPE) == mOP I'm at a loss to determine quite what the intention is. Maybe it should be an array indexed by enum types, maybe a function, maybe something that can be pattern matched on? I don't know. The intention is z0 is a system parameter and database, it contains a set of info needed to define a particular simulation it looks like ( [n,m...], [m,o,p]) n is is a list info settings for the circuit analysis m is a list of statistics for the circuits that is need in sub-sequent calculation m is a list of circuit settings like temperature etc. o is a list of matrix solution for non-linear newton raphson p is a list of matrix solution for time dependent calculations the bug was in o this is a variable length [Double] whose length depends on the size of matrix bieng solved. so. (((fst z0)!!pMSET)!!pMTYPE) == mOP is checking if we are doing mOP type calculations. If this was C this would be a structure of settings and buffer data. fernan -- http://www.fernski.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: newtype deriving, was Re: [Haskell-cafe] is closing a class this easy?
Hi Wolfgang On 18 Jul 2009, at 13:42, Wolfgang Jeltsch wrote: Am Samstag, 18. Juli 2009 11:43 schrieb Conor McBride: The trouble here is that somewhere along the line (GADTs? earlier?) it became possible to construct candidates for p :: * - * which don't respect isomorphism. Hello Conor, I’m not sure whether I exactly understand what you mean here. I think, it’s the following: Say, you have a type A and define a type B as follows: newtype B = B A Then, for any p :: * - *, the type p A should be isomorphic to p B, i.e., it should basically contain the same values. This is no longer true with GADTs since you can define something like this: data GADT a where GADT :: GADT A Now, GADT :: GADT A but not GADT :: GADT B. Is this what you mean? Yes, that's what I mean. These tend to be somewhat intensional in nature, and they mess up the transfer of functionality. Could you maybe elaborate on this? Just as you've shown, we can use GADTs to express a p such that p A is inhabited but p B is not(*) Moreover, we can write type families which make TF A = IO String TF B = String so it'd be better not to get A and B confused. But all of these nasties rely on taking an intensional view of types as pieces of syntax, rather than the extensional view of types as sets of values. Predicates (to use a Curry-Howardism) which rely only on the extensional properties of types can be relied upon to respect isomorphism, and indeed to respect trivial isomorphisms trivially. (You can refine this to *inclusion* if you pay attention to co/contra-variance. This would give us inflate :: Functor f = f Void - f x as a no-op.) Your GADT is an intensional predicate --- being A, rather than having the values of A --- so it respects fewer equations. Consider a type expression t[x], over a free type variable x. Suppose you have some f :: a - b and g :: b - a. For the most part, you can use these to construct t[f,g :: t[a] - t[b] and hence t[g,f :: t[b] - t[a] by recursion on the structure of t. E.g,, x[f, g = f Bool[f, g = id (s - t)[f, g = \ h - t[f,g . h . s[g,f ... You'll find that t[id,id = id. But you'll get stuck at GADTs and type families. Functions both ways don't give you enough information: you need equality (same objects, different morphisms). Type classes are predicates: supporting a dictionary. If they happen to be extensional predicates, then they should support newtype deriving. Can we draw out this distinction somehow? Interesting place to go... Cheers Conor (*) usual caveats for bottom spotters ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] ANNOUNCE: graphviz-2999.0.0.0
I am pleased to announce a new release of the graphviz package for Haskell, which provides bindings to the GraphViz [1] suite of tools. [1] http://www.graphviz.org/ Probably the biggest and most important change in this release is that AFAICT, all 152 attributes utilised/supported by GraphViz [2] are now specified and supported by this library. However, I'm not fully sure how well the parsing of these attributes will turn out; if you notice a bug/problem then please let me know. [2] http://graphviz.org/doc/info/attrs.html I've specified this as being the first in the 2999.0 series of releases. I will switch to 3000.0 when the generic graph class has been released and graphviz switched to using it rather than just FGL. One other future change that I'm considering is to improve the parsing ability of the Dot language. At the moment, graphviz assumes the following layout is followed: * Graph attributes * Nodes with their attributes (clusters are supported only for creation, not parsing). * Edges with their attributes. To match the behaviour of upstream, this will need to be changed into just a list of statements, where a statement is one of five things [3]: * A Node * An Edge * An attribute (either for the graph overall, nodes or for edges) * ID '=' ID (not quite sure what this is; some kind of assignment) * A subgraph (clusters are a specific type of subraph) As the way of defining an attribute for a specific grouping of nodes/edges/subgraphs is to have them all listed after the attribute definition (whereas those beforehand do not have this attribute), the imperative nature of the Dot language does not allow us to split these statements up as we currently do. [3] http://graphviz.org/doc/info/lang.html As such, I'm asking which of the following two choices people would prefer: 1. Follow upstream so that it can fully parse a Dot graph 2. Keep it as it is, so that it is possible to consider all edges, etc. easily. Other major changes to this release: * Fixed a bug where the Show instance and read function for DotEdge had the from/to nodes the wrong way round. This was not immediately noticed since the Graph - DotGraph functions created them the wrong way round, so for those users who only used these this was not apparent. Spotted by Neil Brown. * Greatly improved Attribute usage: almost all attributes are now covered with allowed values. * Extend DotGraph to include whether a graph is strict or not and if it has an ID. Also move the directedGraph field. * Make Dot refer to the actual dot command and DotArrow refer to the ArrowType (rather than DotCmd and Dot as before). * Make the Data.GraphViz.ParserCombinators module available to end users again, but not re-exported by Data.GraphViz; it has a warning message up the top not to be used. It is there purely for documentative purposes. * Use extensible-exceptions so that base 4 is once again supported. * Follow the PVP rather than using dates for versions: http://www.haskell.org/haskellwiki/Package_versioning_policy Note that this means that any library/application using more than a trivial sub-set of graphviz will most likely need to be updated. However, now that the PVP is being followed it should be easier to tell in future when updates will be required. Other items I'm wanting to do in future releases: = * Allow user to choose whether or not the graph is meant to be directed or undirected. * Improve parsing to fully (or at least follow more closely) support Dot. * Improve clustering/subgraph support. * Use a PrettyPrinter rather than Show to generate Dot output. * Improve Output support. * Find and fix the handle closing bug with graphvizWithHandle. -- Ivan Lazar Miljenovic ivan.miljeno...@gmail.com IvanMiljenovic.wordpress.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] can there be (hash-table using) O(n) version of this (I think currently) n log n algo?
Thanks Bulat. FWIW, i take it that http://www.haskell.org/haskellwiki/Shootout/Knucleotide is what Edward was referring to, with the shootouts. It seems that a lot of progress has been made but not much has been migrated back to hackage. Going back to my original question, I am now looking for a dead simple motivating example for showing the example of using a (good) hashtable over Data.Map, with a tangible demo of O(n) over O(n log n) running times. I mean, something where running an input of (10^4) size versus (10^6) size shows a noticeably laggier run when using Set versus hashtable. I don't think maybe my original example quite qualifies because I think in practice the computation is dominated by space complexity. However, I haven't yet ported it over to a hashtable version, so not sure. (And the shootout example doesn't satisfy my sense of dead simple.) 2009/7/18 Bulat Ziganshin bulat.zigans...@gmail.com: Hello Thomas, Saturday, July 18, 2009, 2:24:21 AM, you wrote: Further, is there a hashtable implementation for haskell that doesn't live in IO? Maybe in ST or something? import Prelude hiding (lookup) import qualified Data.HashTable import Data.Array import qualified Data.List as List data HT a b = HT (a-Int) (Array Int [(a,b)]) -- size is the size of array (we implement a closed hash) -- hash is the hash function (a-Int) -- list is assoclist of items to put in hash create size hash list = HT hashfunc (accumArray (flip (:)) [] (0, arrsize-1) (map (\(a,b) - (hashfunc a,(a,b))) list) ) where arrsize = head$ filter (size)$ iterate (\x-3*x+1) 1 hashfunc a = hash a `mod` arrsize lookup a (HT hash arr) = List.lookup a (arr!hash a) main = do let assoclist = [(one, 1), (two, 2), (three, 3)] hash = create 10 (fromEnum . Data.HashTable.hashString) assoclist print (lookup one hash) print (lookup zero hash) -- Best regards, Bulat mailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Haskell Weekly News: Issue 126 - July 18, 2009
--- Haskell Weekly News http://sequence.complete.org/hwn/20090718 Issue 126 - July 18, 2009 --- Welcome to issue 126 of HWN, a newsletter covering developments in the [1]Haskell community. [2]Hac phi is next weekend! With almost 30 people already registered, it looks like we're going to have a fantastic time hacking in Philadelphia. It's still not too late to [3]register! Announcements GHC 6.10.4. Ian Lynagh [4]announced a new patchlevel release of GHC, 6.10.4. This version has very few changes over 6.10.3, but fixes some bugs that could be critical for a few users. See the [5]release notes for details. shelltestrunner 0.6 released. Simon Michael [6]announced the first release of [7]shelltestrunner, a small tool for testing any command-line program by running it through shell tests defined with a simple file format. generator 0.5.1. Yair Chuchem [8]announced the release of the [9]generator package, which implements an alternative list monad transformer, a list class, and related functions. GLURaw 1.0.0.0. Sven Panne [10]announced a new [11]GLURaw package, containing full support for all GLU functionality and similar in spirit to the OpenGLRaw package: it is a 1:1 mapping of the C interface, no libraries or headers are needed at build time, and the GLU API entries are resolved dynamically at runtime. OpenGLRaw 1.0.1.0. Sven Panne [12]announced a new version of the [13]OpenGLRaw package, which adds support for a number of OpenGL extensions. ObjectName 1.0.0.0. Sven Panne [14]announced a (tiny) new package, [15]ObjectName, which contains a class corresponding to the general notion of explicitly handled identifiers for API objects, e.g. a texture object name in OpenGL or a buffer object name in OpenAL. StateVar 1.0.0.0. Sven Panne [16]announced the [17]StateVar package, which further modularizes the OpenGL/OpenAL packages. It implements state variables, which are references in the IO monad, like IORefs or parts of the OpenGL state. data-ordlist-0.0.1 and NumberSieves-0.0. Leon Smith [18]announced the release of two new packages: [19]Data.OrdList offers a convenient way for efficiently dealing with lists that you happen to know are ordered, and includes operations such as union, merge, exclusive union, intersection, and difference. [20]NumberSieves includes the Sieve of O'Neill, from The Geniune Sieve of Eratosthenes by Melissa O'Neill, which offers an incremental primality sieve based on priority queues. Also included are two array-based generalizations of the Sieve of Eratosthenes: one for factoring a large quantity of small numbers, and another for calculating the phi function for a large quantity of small numbers. graphviz-2999.0.0.0. Ivan Lazar Miljenovic [21]announced a new release of the [22]graphviz package for Haskell, which provides bindings to the [23]GraphViz suite of tools. The biggest and most important change in this release is that all 152 attributes utilised/supported by GraphViz are now specified and supported. uncommon IMO problem - toilet management. Henning Thielemann [24]announced a [25]Haskell package for managing toilet use at the International Mathematical Olympiad. darcs 2.3 beta 4. Petr Rockai [26]announced another darcs 2.3 beta release, which features better Windows support. If you're on Windows, you should be able to install it with 'cabal install darcs-beta' -- give it a try! Google Summer of Code Progress updates from participants in the 2008 [27]Google Summer of Code. space profiling. Gergely Patai has been working on a [28]heap profile manager. fast darcs. Petr Rockai put out another [29]another darcs 2.3 beta release, and made a [30]bunch of other progress including getting darcs up and running on win32, working on hashed-storage, and optimizing 'darcs show contents'. Discussion is closing a class this easy? Conor McBride [31]asked for feedback on some code intended to effectively create a closed type class. laziness blowup exercise. Thomas Hartman [32]challenged readers to squash a memory leak. Blog noise [33]Haskell news from the [34]blogosphere. Blog posts from people new to the Haskell community are marked with , be sure to welcome them! * Gergely Patai: [35]Introducing the heap profile manager. * FP Lunch: [36]Folding Statistics. * Petr Rockai: [37]soc progress 8. * Greg Bacon: [38]Monadic takeWhile. * Petr Rockai: [39]darcs 2.3 beta 4. * David Amos: [40]Counting symmetries using transversals. * Magnus Therning: [41]XML prettifier in Haskell. * Petr Rockai: [42]soc progress 7. Quotes of the Week * Berengal: For me, understanding the basics/reasoning behind
Re[2]: [Haskell-cafe] can there be (hash-table using) O(n) version of this (I think currently) n log n algo?
Hello Thomas, Saturday, July 18, 2009, 7:23:10 PM, you wrote: Going back to my original question, I am now looking for a dead simple motivating example for showing the example of using a (good) hashtable over Data.Map spell checking? -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] can there be (hash-table using) O(n) version of this (I think currently) n log n algo?
tphyahoo: The code below is, I think, n log n, a few seconds on a million + element list. Have you tried the judy arrays library on Hackage? (It provides a hashtable, which I've used occasionally) -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANNOUNCE: graphviz-2999.0.0.0
Hi, On Sat, Jul 18, 2009 at 10:23 AM, Ivan Lazar Miljenovic ivan.miljeno...@gmail.com wrote: I am pleased to announce a new release of the graphviz package for Haskell, which provides bindings to the GraphViz [1] suite of tools. Nice work! As the way of defining an attribute for a specific grouping of nodes/edges/subgraphs is to have them all listed after the attribute definition (whereas those beforehand do not have this attribute), the imperative nature of the Dot language does not allow us to split these statements up as we currently do. [3] http://graphviz.org/doc/info/lang.html As such, I'm asking which of the following two choices people would prefer: 1. Follow upstream so that it can fully parse a Dot graph 2. Keep it as it is, so that it is possible to consider all edges, etc. easily. I would vote for the second one since I think that is the most widely used feature of this package. Cheers, Zsolt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: [Haskell] Re: 20 years ago
Richard O'Keefe wrote: On Jul 15, 2009, at 5:25 PM, Benjamin L.Russell wrote: it interesting that you should use the biological term disease; according to a post [1] entitled Re: Re: Smalltalk Data Structures and Algorithms, by K. K. Subramaniam, dated Mon, 29 Jun 2009 11:25:34 +0530, on the squeak-beginners mailing list (see http://lists.squeakfoundation.org/pipermail/beginners/2009-June/006270.html), Concepts in Squeak [a dialect and implementation of Smalltalk] have their origins in biology rather than in computational math That posting is wrong. Smalltalk's roots are very firmly planted in Lisp, with perhaps a touch of Logo (which also had its roots in Lisp). The classic Smalltalk-76 paper even contains a meta-circular interpreter, which I found reminiscent of the old Lisp one. The biological metaphor in Smalltalk is actually a SOCIAL metaphor: sending and receiving messages, and a social model of agents with memory exchanging messages naturally leads to anthropomorphisms. Also of note, the social metaphor is also very mathematical. It has its roots in process calculi like the pi-calculus, petri nets, the join-calculus, etc. The original OOP metaphor of Agents is also strongly aligned to this process calculus interpretation. (And any anthropologist will defy that sociality has more than a primitive connexion with biological systems. Animal behaviorists may disagree.) -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: [Haskell] Re: 20 years ago
Richard O'Keefe wrote: On Jul 15, 2009, at 5:25 PM, Benjamin L.Russell wrote: it interesting that you should use the biological term disease; according to a post [1] entitled Re: Re: Smalltalk Data Structures and Algorithms, by K. K. Subramaniam, dated Mon, 29 Jun 2009 11:25:34 +0530, on the squeak-beginners mailing list (see http://lists.squeakfoundation.org/pipermail/beginners/2009-June/006270.html), Concepts in Squeak [a dialect and implementation of Smalltalk] have their origins in biology rather than in computational math That posting is wrong. Smalltalk's roots are very firmly planted in Lisp, with perhaps a touch of Logo (which also had its roots in Lisp). The classic Smalltalk-76 paper even contains a meta-circular interpreter, which I found reminiscent of the old Lisp one. The biological metaphor in Smalltalk is actually a SOCIAL metaphor: sending and receiving messages, and a social model of agents with memory exchanging messages naturally leads to anthropomorphisms. Also of note, the social metaphor is also very mathematical. It has its roots in process calculi like the pi-calculus, petri nets, the join-calculus, etc. The original OOP metaphor of Agents is also strongly aligned to this process calculus interpretation. (And any anthropologist will defy that sociality has more than a primitive connexion with biological systems. Animal behaviorists may disagree.) -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell Zippers on Wikibooks: teasing! :)
Peter Verswyvelen wrote: After my colleague explained me about zippers and how one could derive the datatype using differential rules, I had to read about it. So I started reading http://en.wikibooks.org/wiki/Haskell/Zippers#Mechanical_Differentiation This page contains the sentence: *For a systematic construction, we need to calculate with types. The basics of structural calculations with types are outlined in a separate chapter **Generic Programming*http://en.wikibooks.org/w/index.php?title=Haskell/Generic_Programmingaction=editredlink=1 * and we will heavily rely on this material* * * However, the generic programming link does not exist yet :-) So although I now have a rough idea about it, I don't understand the details yet, e.g. notation like [image: \mathit{Node}\,A = \mu X.\,\mathit{NodeF}_A\,X] doesn't make much sense to me yet, although I suspect I can read the mu as a lambda on types? |\mu X. T| can be interpreted as |fix (\lambda X. T)| on types (where fix is the function returning the least fixed point of its argument), so you're close. To figure out what this interpretation means, you can just think of it as tying the knot, where the X is the name we give to the recursive type; thus: data List x = Nil | Cons x (List x) == data List x = \mu xs - Nil | Cons x xs -- i.e. xs = \mu xs - Nil | Cons x xs == data ListF x xs = Nil | Cons x xs type List x= \mu xs - ListF x xs ... The full details are a bit more complex because we should distinguish between \mu (least fixed point) and \nu (greatest fixed point). For Haskell data types these two fixed points happen to coincide, but that's not the case in general. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A voyage of undiscovery
Andrew Coppin wrote: That seems simple enough (although problematic to implement). However, the Report seems to say that it matters whether or not the bindings are muturally recursive [but I'm not sure precisely *how* it matters...] Seriously, check out the classic Milner paper. Of languages in the ML tradition, Haskell is actually a bit strange in that it doesn't require the programmer to explicitly annotate recursive functions and recursive groups. That's *very* nice for programmers (since the compiler needs to and can figure it out anyways), though it hides some of the implementation complexity since you need to discover the implicit annotations. Polymorphic recursion was one of the big bugbears in the original HM inference algorithm. We can deal with it now, like we can deal with rank-N polymorphism (aka polymorphic lambda-binding) and many other improvements, but it's easiest to start out with the original algorithm when learning everything. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Problem with lazy IO
Hello. I've tried to combine lazy IO and parsec. The hole process is done by network. Currently I have implemented 'short parsers' so I enter them on need. To update state I have following code: parser2nntp :: Monad m = NntpParser m a - NntpT m a parser2nntp p = do s - NntpT (gets $ input . connection) e - runParserT (do v - p i - getInput return (v, i)) () s case e of Left er - error $ show er Right (v, i') - (NntpT (modify (pNI i')) return v) where pNI :: Monad m = ByteString -NntpState m - NntpState m pNI i s = s {connection = (connection s) {input = i}} However the 4 line (i - getInput) blocks the execution as trace indicated. String returned have no input available so it should block on evaluation - and here I pass only a reference to it (or rather I think so). What's wrong? PS. Full code is in darsc nntp repository http://code.haskell.org/nntp/ - please note that it seems to require network compiled against parsec 3 - not 2. signature.asc Description: This is a digitally signed message part ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A voyage of undiscovery
Andrew Coppin wrote: Robert Greayer wrote: f0 _ = (foo True, foo 'x') where foo = id is well-typed. Really? That actually works? How interesting... This suggests to me that where-clauses also do strange things to the type system. Not too strange, in fact we need it to do that for local definitions to be helpful at all. The short answer is that let-binding is still polymorphic, whereas lambda-binding (passing in a parameter) is monomorphic. If let-binding were not polymorphic, then we could remove it entirely can just desugar everything into lambda-bindings. You should read this classic paper which introduced Hindley--Milner type inference, Robin Milner. A theory of type polymorphism in programming. Journal of Computer and System Sciences, 17:348-375, August 1978. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.67.5276 -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] was: Debugging methods for haskell structured data types the right way in haskell
On Sun, Jul 19, 2009 at 7:40 AM, wren ng thorntonw...@freegeek.org wrote: Fernan Bolando wrote: The intention is z0 is a system parameter and database, it contains a set of info needed to define a particular simulation it looks like ( [n,m...], [m,o,p]) n is is a list info settings for the circuit analysis m is a list of statistics for the circuits that is need in sub-sequent calculation m is a list of circuit settings like temperature etc. o is a list of matrix solution for non-linear newton raphson p is a list of matrix solution for time dependent calculations This would be better as, data SystemParameterDatabase = SystemParameterDatabase { infoSettings :: InfoSettings , statistics :: Statistics , settings :: Settings , nlnr :: [Matrix Double] , timeDependent :: [Matrix Double] } data InfoSettings = InfoSettings { pMSET :: MSET , aSetting :: A , bSetting :: B ... } data Statistics = Statistics { aStatistic :: A , anotherStatistic :: A , bStatistic :: B ... } data Settings = Settings { temperature :: Kelvin , etc :: Etc } ... A single-constructor ADT, especially with the labeled-fields syntax, is pretty close to C structs; no need to reinvent them and give yourself headaches. Really, the only thing you should be using lists for is a variable-length sequence of elements drawn from the same type and distinguished only by their position in the sequence. Whenever the length is fixed or the (semantic) type of elements can be distinguished from one another (or altered by pushing/popping the list), then a list is not what you want to be using because it doesn't capture the intention of the type (and therefore allows unintelligible values of the type, and inappropriate transformations on the type). -- Live well, ~wren This is the kind of code recommendations I was looking. thanks -- http://www.fernski.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging methods for haskell
Fernan Bolando wrote: The intention is z0 is a system parameter and database, it contains a set of info needed to define a particular simulation it looks like ( [n,m...], [m,o,p]) n is is a list info settings for the circuit analysis m is a list of statistics for the circuits that is need in sub-sequent calculation m is a list of circuit settings like temperature etc. o is a list of matrix solution for non-linear newton raphson p is a list of matrix solution for time dependent calculations This would be better as, data SystemParameterDatabase = SystemParameterDatabase { infoSettings :: InfoSettings , statistics:: Statistics , settings :: Settings , nlnr :: [Matrix Double] , timeDependent :: [Matrix Double] } data InfoSettings = InfoSettings { pMSET:: MSET , aSetting :: A , bSetting :: B ... } data Statistics = Statistics { aStatistic :: A , anotherStatistic :: A , bStatistic :: B ... } data Settings = Settings { temperature :: Kelvin , etc :: Etc } ... A single-constructor ADT, especially with the labeled-fields syntax, is pretty close to C structs; no need to reinvent them and give yourself headaches. Really, the only thing you should be using lists for is a variable-length sequence of elements drawn from the same type and distinguished only by their position in the sequence. Whenever the length is fixed or the (semantic) type of elements can be distinguished from one another (or altered by pushing/popping the list), then a list is not what you want to be using because it doesn't capture the intention of the type (and therefore allows unintelligible values of the type, and inappropriate transformations on the type). -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe