Re: [Haskell-cafe] System.Exit
On Thu, Jul 05, 2007 at 02:04:32PM +1000, Thomas Conway wrote: Hi All, Can anyone tell me what System.Exit.exitWith is actually supposed to do? As far as I can tell, it seems to be a synonym of (return ()). Okay, I'll stop being provocative and try and be helpful. So I have a web server, which like the one in The Literature(TM), essentially has a main loop: doit sok = do (reqSok,reqAddr) - Network.Socket.accept sok forkIO (handleRequest reqSok reqAddr) doit sok This is all well and good, but how do you *stop* a server? Well, you have a request (blah blash auth blah blah) which tells it to shut down, /quit for example. I have a function to handle the quit request that looks something like: quitHandler sok addr = do tidyUpEverything sendOkResponse sok sClose sok System.Exit.exitWith ExitSuccess All nice and simple. All except one detail: it doesn't actually work. It prints exit: ExitSuccess but the doit loop keeps going. Of course, it goes totally spacko, because of the call to tidyUpEverything, but it doesn't exit. So, if I set an IORef/TVar inside quitHandler which I inspect either just before or just after the call to Network.Socket.accept, I could exit the loop, but that only helps once the next request comes in. I contemplated a solution involving Control.Exception.throwTo, but I actually read the doco (!) which states the following: quote If the target thread is currently making a foreign call, then the exception will not be raised (and hence throwTo will not return) until the call has completed. This is the case regardless of whether the call is inside a block or not. /quote So no joy there. Ideas anyone? And is exitWith broken, or is it the doco that's broken? The documentation says: | Computation exitWith code throws ExitException code. Normally this | terminates the program, returning code to the program's caller. Before | the program terminates, any open or semi-closed handles are first | closed. | | As an ExitException is not an IOError, exitWith bypasses the error | handling in the IO monad and cannot be intercepted by catch from the | Prelude. However it is an Exception, and can be caught using the | functions of Control.Exception. This means that cleanup computations | added with bracket (from Control.Exception) are also executed properly | on exitWith. Probably some part of your code is catching all exceptions, printing them, and then ignoring them; thus negating the exit request. If you want to ignore all exceptions, you can still use exitImmediately from the unix package, but all the usual caveats (unflushed file buffers, no synchronization, no profile output) apply. Stefan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Lightweight sequent calculus and linear abstractions
Conor McBride has posed an interesting problem: implement constructors P v for embedding pure values v Ofor holes f :$ a for application, left-associative and an interpreting function emmental such that emmental (P (+) :$ (P (*) :$ O :$ P 10) :$ O) 4 2 = 42 I believe one can do better. There is no need for the :$ operation, and there is no need for of lifting non-functional constants. The following code demonstrates a more economical notation. The code essentially implements Hypothetical Reasoning, considering an expression with holes as an (intuitionistic) sequent. Each hole is one formula in the antecedent. The formulas in the antecedent are ordered, so our logic is actually the relevance, substructural intuitionistic logic. The function emmental takes the form of the Deduction Theorem (and its implementation is the proof of the theorem). The test takes the form test_McBride = dt ((ih *! (10::Int)) +! ih) 4 2 where ih = holet (undefined::Int) and gives the predictable answer. Another test, which shows that we can pile up holes (aka hypotheses) at will, and they all line up: test7 = let exp = l1 (map succ) ((1::Int) !: ih !: ih !: ih !: [5]) ih = holet (undefined::Int) deduced = dt exp in deduced 11 12 13 -- [2,12,13,14,6] test_order = dt( (ih `p` ih) `p` (ih `p` ih) ) 1 2 3 4 where ih = holet (undefined::Int) -- ((1,2),(3,4)) It is clear from our examples that our holes are monomorphically typed; the lifted functions don't have to be. We could have implemented things the other way around. We could have played with more complex inferences when applying polymorphic functions to polymorphic sequents. At present, we chose the simplest solution. Here it is. {-# OPTIONS -fglasgow-exts #-} {-# OPTIONS -fallow-undecidable-instances #-} {-# OPTIONS -fallow-overlapping-instances #-} -- the extensions are merely for the sake of IsHypothetical below -- Lightweight sequent calculus: computations on sequents module SEQ where -- Hypothetical value: one formula in the antecedent newtype H a = H a -- The primitive sequent: a |- a hole :: H a - a hole (H x) = x -- The version of the above to make it easy to assign a specific type to it holet :: a - H a - a holet _ = hole -- This class proves, by construction, the Deduction Theorem -- x |- b == x - b class DeductionTh seq r | seq - r where dt :: seq - r instance (IsHypothetical seq f, DeductionTh' f seq r) = DeductionTh seq r where dt = dt' (undefined::f) class DeductionTh' f seq r | f seq - r where dt' :: f - seq - r instance DeductionTh y r = DeductionTh' HTrue (H x - y) (x-r) where dt' _ hf = \x - dt (hf (H x)) instance DeductionTh' HFalse a a where dt' _ = id -- Lifting an a-b function to sequents class Lift1 a b arg res | a b arg - res where l1 :: (a-b) - (arg-res) instance (IsHypothetical arg f, Lift1' f a b arg res) = Lift1 a b arg res where l1 = l1' (undefined::f) class Lift1' f a b arg res | f a b arg - res where l1' :: f - (a-b) - (arg-res) instance Lift1 a b y b' = Lift1' HTrue a b (H x - y) (H x - b') where l1' _ fn arg = \hx - l1 fn (arg hx) -- here we assert a local functional dependency instance TypeCast arg a = Lift1' HFalse a b arg b where l1' _ fn arg = fn (typeCast arg) test1 = dt True test2 :: Int - Int test2 = dt hole test2' = dt (holet (1::Int)) test3 = dt (l1 not True) test4 = dt (l1 not (holet False)) -- expected type error -- test4' = dt (l1 not (holet (1::Int))) test4'' = test4 False -- Lifting an a-b-c function to two sequents -- we should keep the order of formulas in the combined antecedent -- The following is just a funnily written `append' of two sequences class Lift2 a b c arg1 arg2 res | a b c arg1 arg2 - res where l2 :: (a-b-c) - (arg1-arg2-res) instance (IsHypothetical arg1 f1, IsHypothetical arg2 f2, Lift2' f1 f2 a b c arg1 arg2 res) = Lift2 a b c arg1 arg2 res where l2 = l2' (undefined::f1) (undefined::f2) class Lift2' f1 f2 a b c arg1 arg2 res | f1 f2 a b c arg1 arg2 - res where l2' :: f1 - f2 - (a-b-c) - (arg1-arg2-res) -- First, drain the antecedent formulas from arg1 instance Lift2 a b c y1 arg2 r = Lift2' HTrue f2 a b c (H x1 - y1) arg2 (H x1 - r) where l2' _ _ fn arg1 arg2 = \hx1 - l2 fn (arg1 hx1) arg2 -- now, add the antecedent formulas from arg2, if any instance Lift2 a b c x1 y2 r = Lift2' HFalse HTrue a b c x1 (H x2 - y2) (H x2 - r) where l2' _ _ fn arg1 arg2 = \hx2 - l2 fn arg1 (arg2 hx2) instance (TypeCast x1 a, TypeCast x2 b) = Lift2' HFalse HFalse a b c x1 x2 c where l2' _ _ fn arg1 arg2 = fn (typeCast arg1) (typeCast arg2) -- Time for tests infixl 6 +! infixl 7 *! infixr 5 !: x +! y = l2 (+) x y x *! y = l2 (*) x y x `p` y = l2 (,) x y x !: y = l2 (:) x y test5 = dt ((1::Int) +! (2::Int)) test51 = dt (holet (1::Int) +! (2::Int)) test51' = test51 10 -- 12 test52 = dt
Re: [Haskell-cafe] folds with escapes
Can you do dropWhile in terms of foldr? One can write foldr that represents drop or dropWhile of the original foldr. One can do even more: zip two folds. That is, obtain a fold that is equivalent to zipping up two lists represented by the original folds. Even furthermore, one can do all these things without recursion (neither at the value level, nor at the type level). http://okmij.org/ftp/Algorithms.html#zip-folds ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Deadlock in real number multiplication (Was: Where's the problem ?)
R Another interesting thing I've discovered is: Prelude length [1..100] R 100 Prelude Data.List.genericLength [1..100] R *** Exception: stack overflow R Maybe there is something wrong with Integer ? No, there is something wrong with genericLength: Prelude Data.List.foldl (+) 0 $ map (const 1) [1..100] :: Int *** Exception: stack overflow Prelude Data.List.foldl' (+) 0 $ map (const 1) [1..100] :: Integer 100 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On Thu, Jul 05, 2007 at 08:50:42AM +1000, Donald Bruce Stewart wrote: [useful stuff] So, in fact pretty much everything I was looking for exists, in some form or other! It's just a bit hard to find at the moment, perhaps because none of this stuff is regarded as 'core Haskell' by any of the tutorials, books etc etc. I'll have a play with some of the libraries mentioned upthread anyway. Thanks everyone. Phil -- http://www.kantaka.co.uk/ .oOo. public key: http://www.kantaka.co.uk/gpg.txt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
I was explaining Haskell to a perl/python hacking friend recently and characterized things thus: Perl is a horrible language with fantastic libraries. Haskell is a fantastic language with horrible libraries. Actually, many of the libraries that exist for Haskell *are* fantastic, it's just that Haskell lacks the *coverage* that Perl or Python have. cheers, T. -- Dr Thomas Conway [EMAIL PROTECTED] Silence is the perfectest herald of joy: I were but little happy, if I could say how much. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] System.Exit
On Wed, Jul 04, 2007 at 11:16:20PM -0700, Stefan O'Rear wrote: The documentation says: | Computation exitWith code throws ExitException code. Normally this | terminates the program, returning code to the program's caller. Before | the program terminates, any open or semi-closed handles are first | closed. | | As an ExitException is not an IOError, exitWith bypasses the error | handling in the IO monad and cannot be intercepted by catch from the | Prelude. However it is an Exception, and can be caught using the | functions of Control.Exception. This means that cleanup computations | added with bracket (from Control.Exception) are also executed properly | on exitWith. Probably some part of your code is catching all exceptions, printing them, and then ignoring them; thus negating the exit request. I think the problem here is that uncaught exception are not propagated from child threads to the main thread (I'm not claiming that they should be) and ExitException only ends the program when caught in the main thread, as it seems. Try this: import Control.Concurrent import System.Exit main = do forkIO $ exitWith ExitSuccess threadDelay 1000 Best regards Tomek ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Write a library today! Was: Binary serialization, was Re: Abstraction leakAKa
drtomc: I was explaining Haskell to a perl/python hacking friend recently and characterized things thus: Perl is a horrible language with fantastic libraries. Haskell is a fantastic language with horrible libraries. Actually, many of the libraries that exist for Haskell *are* fantastic, it's just that Haskell lacks the *coverage* that Perl or Python have. Yes, and we know exactly what to do about this. hackage.haskell.org is growing by a few packages a week -- and anyone who binds to any C lib should just upload their stuff. So ... if you're reading this message -- please upload a library today, and more than just a few of us might have nice Haskell jobs tomorrow! -- Don P.S. Maybe we should run 'bindathons' or have CPAN-style contests to get new libraries written? If you're bored, write a binding to some C lib, that python, ruby or perl have already got a binding to. Do it! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] folds with escapes
Can you do dropWhile in terms of foldr? I don't see how. If you are really keen, you might want to try altering the working backwards with tuples version into one which is properly lazy (many people who read the paper pointed out the omission). you might want to mention the story of the predecessor function in church numerals (where data structures are represented as their right folds, and the predecessor function goes against the grain of that recursion, but can be defined using pairing/returning functions)? for some history/anecdotes: The Impact of the Lambda Calculus in Logic and Computer Science, Barendregt, Bulletin of Symbolic Logic, 1997, section 2, paragraph 2 http://citeseer.ist.psu.edu/barendregt97impact.html for the tupling trick applied to dropWhile and primitive recursion, Graham's tutorial has already been mentioned: A tutorial on the universality and expressiveness of fold Graham Hutton. Journal of Functional Programming, 1999, section 4 http://www.cs.nott.ac.uk/~gmh/bib.html#fold claus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Deadlock in real number multiplication (Was: Where's the problem ?)
Philip Armstrong wrote: genericLength :: (Num i) = [b] - i genericLength []= 0 genericLength (_:l) = 1 + genericLength l So genericLength is lazily building up unevaluated (+) expressions and running out of stack space. Is there a good reason for genericLength to be lazy? Yes, since addition in i may well be lazy. data Nat = Zero | Succ Nat instance Num Nat where Zero + b = b (Succ a) + b = Succ (a + b) ... natLength :: [a] - Nat natLength = genericLength Also, you can turn the foldr into a foldl' with a cleverly chosen data type like data Int' = I Int | Plus Int' Int' eval :: Int' - Int eval = eval' 0 where eval' (I i) k = k + i eval' (Plus x y) k = eval' y $! eval' x k instance Num Int' where (+) = Plus ... or in its bare essence newtype DiffInt = DI { unDI :: Int - Int } instance Num DiffInt where (+) f g k = DI $ unDI g $! unDI f k evalDI :: DiffInt - Int evalDI f = unDI f 0 Regards, apfelmus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Playing with delimited continuations
The ZFS library contains the most up-to-date implementation of the CC monad and the transformer. I have a few other versions scattered around, but they are probably not relevant. I found the CC_FrameT.hs to be the fastest one. Is that you can think of normal continuations as delimited continuations with a global prompt p0 that denotes the end of the computation. You can emulate this using the reader monad to store the prompt: Alternatively, one can use implicit parameters. They are quite handy in this case. So, I suppose my first question is if anyone can see a better way of generalizing the types of the control operators to work with the arbitrarily nested monad stacks typically used in MTL. I believe the answer to this question is NO. That means, (delimited) continuations expose the fundamental limitation of monadic transformers. Monadic transformation approach imposes the strict separation of layers. They layers are fixed at compile time and can't dynamically change. Alas, there are many _practically significant_ circumstances where the layers have to change dynamically, have to interleave. Our ICFP06 paper discusses this point a bit, and the accompanying code contains the relevant examples. http://okmij.org/ftp/packages/DBplusDC-README.txt Please see the README file and the file reader.hs in the source code. When we first realized that monadic transformers had a significant limitation, we too felt odd. Please see also below. First, the prompt module needs to use unsafeCoerce, or something equivalent. But, of course, unsafeCoerce feels dirty to me, and it'd be nice if some cool type system hackery could be used instead of going around the type system. Alternatively, if we have reference cells available (STRef or IORef), then we don't need unsafeCoerce. The whole code is pure Haskell with no unsafe operations, and is type safe and sound. This outcome is not an accident: given monadic style, the CC monad and reference cells are `equivalent'. Given one, we can get the other. Any type system that is capable of typing reference cells will give us delimited continuations (provided we have the monadic style so we can deal with the `stack'). One part of that claim, from multi-prompt delimited continuations to reference cells, was formulated and proven in the ICFP06 paper. The converse was formulated in an appendix to the paper, which was taken out because we ran out of space-time. The proof was done by construction, which is not generally available (although the pure OCaml implementation of CC shows how that can be done). The only drawback of using STRef or IORef to implement CC is that CC is no longer a transformer (because neither ST nor IO are). That may not be such a big drawback as the only benefit of CC being transformer (for us, at least) is that we can lay it out over the IO monad. Well, actually there is another benefit, of limiting the effects of the code: even if the CC m code will execute in the IO monad, the code cannot know that. Incidentally, there is actually little need to mix CC with other monad transformers like reader, writer, RWST, Error, etc. The CC monad subsumes them all! That is the important theoretical result by Filinski: delimited continuations can express every expressible monad. This has important practical benefits: we can use real names (variables of the type Prompt) to operate various pieces of state, environment, errors, etc. We no longer need to count the number of 'lift'. The overall performance may be better, too: each monadic layer adds at least one closure. CC monad can implement threads, and I have a hunch CC monad can implement STM. Second is a minor point. There's a sequence datatype in the paper that represents the delimited stack: data Seq s r a b ... Which represents a sequence of frames that take a value of type 'a' to a value of type 'b'. The paper mentions that the empty constructor should have type 'Seq s r a a', but that it's impossible to do that, so they instead have it take a function that provides evidence of the equivalence between a and b, using 'id' and a smart constructor to have the same effect. But, with GADTs, it's now possible to have a constructor with the right type directly, so I did that in my implementation. Have you checked the latest draft of the paper from Amr Sabry's home page? They might have changed that point. Anyway, there is an implementation data Seq s r a = PushP (Prompt.Prompt r a) (Seq s r a) | forall c. PushSeg (s r a c) (Seq s r c) | forall c. PushCO (a - c) (Seq s r c) type SubSeq s r a b = Seq s r b - Seq s r a that has no EmptyS constructor as you can see. So, the trouble you have encountered goes away. The authors are aware of that minor point. The point is truly minor so perhaps it is not bothering with. If you'd like that code, please check with the authors first, because it is wholly based on their work.
Re: [Haskell-cafe] A very nontrivial parser
Andrew Coppin [EMAIL PROTECTED] wrote: My goal is to be able to stack multiple parsers one on top of the other - but be able to *change* the stack half way through parsing if needed. Essentially, I have the stacked function, where if I do x - stacked foo parser1 bar parser2 y - parser3 then it runs parser2, but it uses parser1 to transform the data first. I can't help thinking that all you really want to do is parse the same data twice, through an intermediate representation. That only requires you to feed the result of one parse into a top-level call to a different parser. For instance: this = do tmp - parser1 x - return (runParser parser2 bar tmp) y - parser3 ... = runParser this foo input In the example, 'parser2' takes a different state type, and a different source token representation from 'parser1' and 'parser3'. No fearsome stack type is needed. :-) Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Lightweight sequent calculus and linear abstractions
Hi Oleg On 5 Jul 2007, at 07:15, [EMAIL PROTECTED] wrote: Conor McBride has posed an interesting problem: implement constructors P v for embedding pure values v Ofor holes f :$ a for application, left-associative and an interpreting function emmental such that emmental (P (+) :$ (P (*) :$ O :$ P 10) :$ O) 4 2 = 42 I believe one can do better. There is no need for the :$ operation, and there is no need for of lifting non-functional constants. I was hoping for something of the sort. I'm glad you could oblige. The following code demonstrates a more economical notation. The code essentially implements Hypothetical Reasoning, considering an expression with holes as an (intuitionistic) sequent. Each hole is one formula in the antecedent. The formulas in the antecedent are ordered, so our logic is actually the relevance, substructural intuitionistic logic. The function emmental takes the form of the Deduction Theorem (and its implementation is the proof of the theorem). That's what I had in mind. The test takes the form test_McBride = dt ((ih *! (10::Int)) +! ih) 4 2 where ih = holet (undefined::Int) and gives the predictable answer. But perhaps you are cheating a bit... infixl 6 +! infixl 7 *! infixr 5 !: x +! y = l2 (+) x y x *! y = l2 (*) x y x `p` y = l2 (,) x y x !: y = l2 (:) x y ...with lifting defined per arity. Of course you can use arity-specific overloading to hide the Ps and :$s, but you haven't given a closed solution to the general problem. By the way, we should, of course, also permit holes in function positions... *Emmental emmental (O :$ P 3) (2 +) 5 ...but I don't imagine that's a big deal. So neither situation is particularly satisfying. I have a noisy but general solution; you have a technique for delivering less noisy solutions in whatever special cases might be desirable. I wonder if we can somehow extract the best from both. You've certainly taught me some useful tricks! Many thanks Conor ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] System.Exit
FWIW, I implemented the STM based solution, and it works a treat. It's less of a hack than the version where I got the child thread to send a SIGINT. ;-) T. -- Dr Thomas Conway [EMAIL PROTECTED] Silence is the perfectest herald of joy: I were but little happy, if I could say how much. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Parsers are monadic?
(b) i like my combinator grammars to be reversible, so that a single grammar specification can be used for both parsing and unparsing/pretty-printing. that means i have to define the details myself anyway. the latest such experiment is not necessarily the simplest variant, for instance, it explicitly gives semantic functions and their inverses, which i've found to be useable compromise in practice. but if you apply a bit of generic programming to associate an ast node with its constructor and children (or if you use an untyped representation of the ast, like 'data AST = Node ConstructorTag [AST]'), with constructor tags that can be compared for equality, you can avoid even that bit of duplication. also, i should have mentioned that the same idea, of using a single grammar specification in parse or unparse mode, opens up a variety of other application possibilities. i already touched upon syntax-directed editing (use a zipper combined with i/o to allow interactive navigation of the ast; associate each type of ast node with its grammar rule; unparse the current node with its rule to display it, let the user edit, then parse the input with the rule for the current node, and continue navigation). another interesting option is to use combinator grammars to specify dialogue protocols: if one annotates the positions in grammar rules where activity switches between dialogue partners, such as server and client communicating according to some protocol, then both server and client can run the same grammar code, in complementary modes, using the switch points to move from producing to expecting dialogue, and vice versa. i've attached a silly little example, using which: $ runhaskell Dialogue.hs server HTTP/1.1 200 Content-Length: 15 Content-Type: text/plain this is a text $ runhaskell Dialogue.hs server | runhaskell.exe Dialogue.hs client this is a text as i said, many opportunities, and i've sometimes wondered why noone else seems to use this technique. perhaps i'll get around to writing it up some day, after all these years.. claus Dialogue.hs Description: Binary data ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Playing with delimited continuations
On Thursday 05 July 2007, [EMAIL PROTECTED] wrote: I believe the answer to this question is NO. That means, (delimited) continuations expose the fundamental limitation of monadic transformers. I suppose this is a bit disheartening, but I suppose it's also good to know I wasn't totally off track. Closure is nice. Our ICFP06 paper discusses this point a bit, and the accompanying code contains the relevant examples. http://okmij.org/ftp/packages/DBplusDC-README.txt Please see the README file and the file reader.hs in the source code. I stuck this on my reading list during my brief searches a few days ago. I'll have to get busy reading it. Alternatively, if we have reference cells available (STRef or IORef), then we don't need unsafeCoerce. The whole code is pure Haskell with no unsafe operations, and is type safe and sound. Good to know. I suppose ST gives me less of an icky feeling than unsafeCoerce. Incidentally, there is actually little need to mix CC with other monad transformers like reader, writer, RWST, Error, etc. The CC monad subsumes them all! This had actually crossed my mind, although making CC work more like the rest of the monads in MTL, rather than the somewhat more isolated ST seemed like a noble goal. Perhaps time would be better spent working out analogues/instances of classes using just the CC monad, though, for times when you want to use the interfaces (but not necessarily the actual transformers, due to the issues above) along with delimited continuations. I suppose it's something to think about. Have you checked the latest draft of the paper from Amr Sabry's home page? They might have changed that point. Anyway, there is an implementation data Seq s r a = PushP (Prompt.Prompt r a) (Seq s r a) | forall c. PushSeg (s r a c) (Seq s r c) | forall c. PushCO (a - c) (Seq s r c) type SubSeq s r a b = Seq s r b - Seq s r a that has no EmptyS constructor as you can see. So, the trouble you have encountered goes away. The authors are aware of that minor point. The point is truly minor so perhaps it is not bothering with. If you'd like that code, please check with the authors first, because it is wholly based on their work. As a matter of fact, I had two versions of the paper, but neither was the latest. The newest version (if it's what I now have) does use GADTs to enforce the 'Seq s r a a' type of EmptyS, but more surprisingly than that (to me, at least), it no longer has a coercion constructor, as they no longer use functions for evidence. Instead, it uses another GADT as the evidence, and unsafeCoerce on that. Eliminating PushCO and such altogether seems attractive. Anyhow, thanks for the input, and the pointers to the papers and such (and writing so many of them in the first place. :) Incidentally, I really enjoyed your Delimited continuations in operating systems paper. Reading that one really made things click for me as to how delimited continuations can actually show up in real systems, as opposed to just being an esoteric, abstract construct). Regards, Dan Doel ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Profiling and Threading: never the twain shall meet
Hi Haskellers, It seems that profiling and threading are not supported at the same time in GHC6.6. At least, it objects to using both the flags at the same time, and there's a Trac entry for that issue. So I just wanted to be sure that I really need threading. I'm passing text through some filters written in perl, just ordinary command line programs. I do it like this: do (hin, hout, herr, ph) - runInteractiveProcess cmd args Nothing Nothing forkIO $ hPutStr hin content hClose hin out - hGetContents hout return (ph, out) which seems to require threading. If I compile without, it will hang indefinitely, I presume deadlocked. Is there a way this can be done without threading? But it's not a great issue for me if I can't do profiling in this case. I just wanted to try out the feature, and it seemed worthwhile checking I was doing this right. Cheers, Dougal. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On Thursday 05 July 2007, Thomas Conway wrote: I was explaining Haskell to a perl/python hacking friend recently and characterized things thus: Perl is a horrible language with fantastic libraries. Haskell is a fantastic language with horrible libraries. Actually, many of the libraries that exist for Haskell *are* fantastic, it's just that Haskell lacks the *coverage* that Perl or Python have. Can't say I agree. I've been learning Python, and have been very un-impressed so far with its library coverage, which I would rate no better than (in terms of the POSIX bindings, worse than) Haskell. The one thing off the top of my head that Python had was Base64, but that's 20 lines of Haskell tops. Aside from that, nothing. Jonathan Cast http://sourceforge.net/projects/fid-core http://sourceforge.net/projects/fid-emacs ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On 05/07/07, Jonathan Cast [EMAIL PROTECTED] wrote: Can't say I agree. I've been learning Python, and have been very un-impressed so far with its library coverage, which I would rate no better than (in terms of the POSIX bindings, worse than) Haskell. It probably depends on your perspective. I've found lots of tasks that would be a simple library call in Python, but which require me to write the code myself in Haskell. Examples: * Send an email * Parse an ini file * Gzip compress a data stream * Calculate the MD5 checksum of a file (Of course, I may just not have found the relevant library - that says something about discoverability rather than coverage, I guess). For bindings, Python's Windows bindings (pywin32) are superb, where Haskell's are minimal and unmaintained. Of course, that won't matter to you if you use POSIX... The one thing off the top of my head that Python had was Base64, but that's 20 lines of Haskell tops. Aside from that, nothing. But that's 20 lines of code I don't want to write, and more, I don't know how to write (without looking up the definition of Base64). Having lots of these seemingly trivial helpers available out of the box is what library coverage means to me. (And Python does have lots of these - I don't know how Haskell fares in practice). I'm not trying to start (or fan) a flamewar, but it's interesting how different people's perspectives on libraries can be... Paul. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
Hello Paul, Thursday, July 5, 2007, 7:00:46 PM, you wrote: * Gzip compress a data stream zlib * Send an email * Parse an ini file The one thing off the top of my head that Python had was Base64, but that's 20 MissingH * Calculate the MD5 checksum of a file crypto -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On 05/07/07, Bulat Ziganshin [EMAIL PROTECTED] wrote: * Gzip compress a data stream zlib * Send an email * Parse an ini file The one thing off the top of my head that Python had was Base64, but that's MissingH * Calculate the MD5 checksum of a file crypto Thanks. The need I had for these is no longer current, but sometime I'll try an experiment and see how easy it is, on a relatively clean Windows box with just GHC installed, to grab and use these libraries. (Side note: with Python, I'm used to 3rd party modules being available as Windows installer packages - does the concept of an installable binary for something like MissingH, which I can just install and use, make sense for a compiled language like Haskell? The build, find I'm missing a C library, get it, compile it, fix bugs, try again cycle I used to hit before Python Windows installers became common isn't something I'd like to repeat...) As I mentioned in passing, it may well be that the library issue with Haskell is more of a perception (or maybe organisational) issue than a technical one... Paul. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On Thu, Jul 05, 2007 at 09:41:23AM -0700, Dave Bayer wrote: There are people who claim with a straight face that they migrated to OS X primarily to use TextMate http://www.textmate.com Presumably you mean http://macromates.com/ ? Phil -- http://www.kantaka.co.uk/ .oOo. public key: http://www.kantaka.co.uk/gpg.txt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
Hi It's not a great experience now, but hopefully things are moving in the right direction. - Found crypto 3.0.3 on hackage. - Tried to build, it depends on NewBinary Cabal-install is intended to remove this problem, so that you can say i want crypto and it gets everything that requires. - Found that on hackage, downloaded and built OK. Lots of scary warnings about happy, greencard etc, not being found during configure, but let's go on. I've complained about these before, although I don't think anyone considered doing anything about it. - Installed NewBinary as I didn't know how to make crypto find it without installing it. I'm a bit nervous, as I don't know how to *un*install it after I've finished. And it installed to my C drive, where I'd really rather it went somewhere else. There is probably documentation on how to do this, but remember, all I really want to do is to write a tiny program to get the MD5 checksum of a file. --prefix should put it where you want. What you really want is a Windows user interface, which is what I want too. - crypto builds and installs OK. But where are the docs? Not installed anywhere obvious, not on hackage. Try google. You can install them with runhaskell Setup haddock, but I have no idea where they end up. They will be on hackage at some point, with cross-indexing etc. - But no simple examples, and the haddoc docs show APIs, but not usage examples! Complain to the author. I always try and include a manual with at least one short example of how to use the library to do something interesting. Unfortunately all these things take time, something that not everyone has. I see you've already responded, and we're in broad agreement. So I won't labour the point. It's an infrastructure issue rather than a technical one, and it *will* improve. What will be interesting is how much the generally lousy Windows experience can be improved Part of the problem is that the number of Windows Haskell developers is low. Another part of the problem is that some people have scorn and contempt for Windows. Alas, those things are hard to change. Thanks Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On Jul 5, 2007, at 8:00 AM, Paul Moore wrote: It probably depends on your perspective. I've found lots of tasks that would be a simple library call in Python, but which require me to write the code myself in Haskell. Examples: * Calculate the MD5 checksum of a file How's this, only one line is specific to your problem: import System.Process import IO doShell :: String - IO String doShell cmd = do (_,out,_,_) - runInteractiveCommand cmd hGetContents out main :: IO () main = do md5 - doShell md5 -q md5.hs putStrLn md5 It's not like you'll be kicked out of the tree house for leaving the Haskell world to get things done. For example, ghostscript and pdf2ps are well-supported open source tools for converting PS to PDF, that can be called from most languages. What's the deal with everyone rewriting PDF handling in their pet language, when it's so much easier to generate Postscript? I'd call that Balkanization; if I were managing a software group, I'd never let that happen. The true problem isn't adequate libraries in each language, it's interoperability so great open-source tools can get written once and then be supported by a cast of thousands. There are people who claim with a straight face that they migrated to OS X primarily to use TextMate http://www.textmate.com which is a GUI editor getting Emacs-like buzz, making Emacs seem by comparison like your grandfather's razor. It's as much a text-based operating system as an editor, and the whole thing is glued together with hundreds of snippets of code one can hack, written in every scripting language imaginable. Polyglots feel right at home... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On 05/07/07, Paul Moore [EMAIL PROTECTED] wrote: The need I had for these is no longer current, but sometime I'll try an experiment and see how easy it is, on a relatively clean Windows box with just GHC installed, to grab and use these libraries. Just for fun I had a go with crypto: - Found crypto 3.0.3 on hackage. - Tried to build, it depends on NewBinary - Found that on hackage, downloaded and built OK. Lots of scary warnings about happy, greencard etc, not being found during configure, but let's go on. - Installed NewBinary as I didn't know how to make crypto find it without installing it. I'm a bit nervous, as I don't know how to *un*install it after I've finished. And it installed to my C drive, where I'd really rather it went somewhere else. There is probably documentation on how to do this, but remember, all I really want to do is to write a tiny program to get the MD5 checksum of a file. Ah, well. Carry on. - crypto builds and installs OK. But where are the docs? Not installed anywhere obvious, not on hackage. Try google. - Found the crypto website, but aargh! It looks like 3.0.3 is out of date and there's a 4.x available. Never mind, that's not likely to have changed. - But no simple examples, and the haddoc docs show APIs, but not usage examples! Going for the obvious approach: import System.IO import Data.Digest.MD5 main = do h - openBinaryFile md5.hs ReadMode s - hGetContents h hClose h md5 - hash s No surprise, this doesn't work. After all, hash wants [Octet], not String. OK, I know this is now getting beyond library availability. But it doesn't compare well to Python's I want an md5 checksum of a file - check the docs, there's a library function built in, use it, no problems. I see you've already responded, and we're in broad agreement. So I won't labour the point. It's an infrastructure issue rather than a technical one, and it *will* improve. What will be interesting is how much the generally lousy Windows experience can be improved - as Duncan points out, installing development libraries on Windows, whether Haskell or C, is a hugely irritating pain. If no-one has found a good answer for C in all these years, it would be great if Haskell could even do slightly better :-) Regards, Paul. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On Thu, 2007-07-05 at 17:07 +0100, Paul Moore wrote: On 05/07/07, Bulat Ziganshin [EMAIL PROTECTED] wrote: * Gzip compress a data stream zlib * Send an email * Parse an ini file The one thing off the top of my head that Python had was Base64, but that's MissingH * Calculate the MD5 checksum of a file crypto Thanks. The need I had for these is no longer current, but sometime I'll try an experiment and see how easy it is, on a relatively clean Windows box with just GHC installed, to grab and use these libraries. Just to warn you, a lot of haskell packages that bind to C libs are much harder to get working on Windows, the zlib package for example. This is because on all other platforms zlib comes with the system and is installed in a location where any application can link to it. On Windows there is no equivalent of /usr/lib you cannot easily install a C lib somewhere that it can be used by any .exe on the system. To make things easier yuo could avoid using -fvia-C and then at least the zlib header files would not need to be installed, but to run a program that uses the zlib package you'd still have to copy the zlib.dll into the same dir as your .exe. There is a mechanism in newer versions of Windows that allows installing .dlls systemwide where any .exe can use them, however ghc and the gcc toolchain do not support them yet. It requires embeding xml manifests into the .dll and .exe files and you have to be the admin user to install one of these systemwide .dll things. It's all a bit of a pain. Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[4]: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
Hello Paul, Thursday, July 5, 2007, 8:07:34 PM, you wrote: note: with Python, I'm used to 3rd party modules being available as Windows installer packages - does the concept of an installable binary for something like MissingH, which I can just install and use, make sense for a compiled language like Haskell? The build, find I'm all cabalized libraries are installed using the same commands: runghc setup.hs configure runghc setup.hs build runghc setup.hs install after this, you just import modules you need in your program and when you build your program, ghc automatically links in all the library functions you used As I mentioned in passing, it may well be that the library issue with Haskell is more of a perception (or maybe organisational) issue than a technical one... the problem exists and for me, it's most important Haskell insfrastructure problem. but things you are mentioned are already implemented i personally implemented several libs required for my own program; and still miss ease-to-use and maintained GUI library -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On 05/07/07, Dave Bayer [EMAIL PROTECTED] wrote: How's this, only one line is specific to your problem: [...] md5 - doShell md5 -q md5.hs Doesn't work on my (Windows) PC, where I have no md5 command available. While I agree in theory with the idea of combining focused tools, it's a potential portability nightmare, particularly on Windows where decent command line tools are almost non-existent on a clean install. You're changing the problem from finding a Haskell library (which only needs to be installed on the development machine at compile time) to finding a 3rd party utility, which has to be installed at runtime on any machine using the compiled Haskell program. Not a good trade-off. And I'm not going to get into Windows/Linux arguments... :-) Paul. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On 05/07/07, Neil Mitchell [EMAIL PROTECTED] wrote: - But no simple examples, and the haddoc docs show APIs, but not usage examples! Complain to the author. Yes, that's completely unrelated to library availability issues. I got off the topic, in all my ranting. Sorry. Part of the problem is that the number of Windows Haskell developers is low. Another part of the problem is that some people have scorn and contempt for Windows. Alas, those things are hard to change. Agreed. I'm extremely grateful for all the contributions people *do* make, even where they don't fit my environment as well as I might like. Anyway, I'm running out of time for today, so I'll leave this thread now. Thanks to all for some interesting comments and pointers! Paul. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On Thu, 2007-07-05 at 17:39 +0100, Paul Moore wrote: I see you've already responded, and we're in broad agreement. So I won't labour the point. It's an infrastructure issue rather than a technical one, and it *will* improve. What will be interesting is how much the generally lousy Windows experience can be improved - We have this slightly odd problem where half our user base use Windows (according to the GHC user survey) but almost every active developer uses Linux or OSX (or a few other BSD/Unix OSs). So we could enormously improve the Windows user experience (and a few heroes work hard on doing just that) but basically there just aren't enough developers who use windows to give it a satisfactory level of support. This is of course a slightly circular problem, since using/developing Haskell on Windows is a pain, developers avoids it and so there are not enough developers irritated by how difficult it is to motivate developers to fix it! Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser
Malcolm Wallace wrote: I can't help thinking that all you really want to do is parse the same data twice, through an intermediate representation. That only requires you to feed the result of one parse into a top-level call to a different parser. For instance: this = do tmp - parser1 x - return (runParser parser2 bar tmp) y - parser3 ... = runParser this foo input In the example, 'parser2' takes a different state type, and a different source token representation from 'parser1' and 'parser3'. No fearsome stack type is needed. :-) For the Nth time... The amount of data processed by parser1 needs to depend on the amount of data processed by parser2. (The amount of data output by each parser is very nontrivially related to the amount of data consumed.) How do you propose to pull that off? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser
Jonathan Cast wrote: On Wednesday 04 July 2007, Andrew Coppin wrote: Anybody have a solution to this? newtype Parser state x y = Parser (forall src. Source src = (state, src x) - (state, src x, y)) ...OK, anybody have a solution that works in Haskell 98? Definition of monad functions, etc, works exactly as for your version. Not so. In fact, doing this causes all mannar of malfunctions. First I get lots of messages of the form Cannot (yet) use update syntax on non-Haskell98 types. Then I get lots of Cannot use function 'foo' as a selector. And then I get My brain has exploded. I can't handle pattern bindings in existentially-quantified type constructors. (?!) And after that I get Type variable 'bar' escapes pattern binding. And finally, after I correct all of those, I get an error saying that the compiler can't match [the hidden type variable] against [some suitable type for that variable]. And in a pattern of all things! (Surely if it's not the right type at runtime, it should generate an exception, just like if you use the wrong constructor...?) In all, the whole thing just malfunctions horribly and I can get no useful work done! _ So my next plan was to write the code as normal, and then create a front-end module which hides all the messy types. But then I just get a whole bunch of escaping type variable errors again. Basically everything I tried make the code drastically more complicated, and even *then* certain parts of it (most especially the stack function) wouldn't compile. So *neeer* :-P ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On Thu, Jul 05, 2007 at 06:08:45PM +0100, Duncan Coutts wrote: On Thu, 2007-07-05 at 17:51 +0100, Neil Mitchell wrote: - Found that on hackage, downloaded and built OK. Lots of scary warnings about happy, greencard etc, not being found during configure, but let's go on. I've complained about these before, although I don't think anyone considered doing anything about it. We know what needs to change, but it's not a trivial change. If anyone's interested, this is the Cabal bug for it: http://hackage.haskell.org/trac/hackage/ticket/132 Thanks Ian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Lightweight sequent calculus and linear abstractions
On 5 Jul 2007, at 18:35, Chung-chieh Shan wrote: [EMAIL PROTECTED] wrote in article [EMAIL PROTECTED] in gmane.comp.lang.haskell.cafe: Conor McBride has posed an interesting problem: implement constructors P v for embedding pure values v Ofor holes f :$ a for application, left-associative and an interpreting function emmental such that emmental (P (+) :$ (P (*) :$ O :$ P 10) :$ O) 4 2 = 42 Hrm! I don't see the original message where the problem was posed, but it is indeed interesting. Here is my solution, but I don't need P, O, and :$ to be constructors, so I rename them to p, o, and $:, respectively: emmental m = m id p x k = k x o k = k (m $: n) k = m (\f - n (\x - k (f x))) infixl 0 $: test = emmental (p (+) $: (p (*) $: o $: p 10) $: o) 4 2 -- 42 Very nice! Thanks Conor ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Lightweight sequent calculus and linear abstractions
[EMAIL PROTECTED] wrote in article [EMAIL PROTECTED] in gmane.comp.lang.haskell.cafe: Conor McBride has posed an interesting problem: implement constructors P v for embedding pure values v Ofor holes f :$ a for application, left-associative and an interpreting function emmental such that emmental (P (+) :$ (P (*) :$ O :$ P 10) :$ O) 4 2 = 42 Hrm! I don't see the original message where the problem was posed, but it is indeed interesting. Here is my solution, but I don't need P, O, and :$ to be constructors, so I rename them to p, o, and $:, respectively: emmental m = m id p x k = k x o k = k (m $: n) k = m (\f - n (\x - k (f x))) infixl 0 $: test = emmental (p (+) $: (p (*) $: o $: p 10) $: o) 4 2 -- 42 All credit is due to Danvy and Filinski (DIKU TR 89/12, Section 3.4; later Danvy's functional unparsing paper, JFP 8(6)). One way to understand this code is that o is like the word what in a language like Mandarin (shenme) or Japanese (dare) that does not move any wh-word to the boundary of a clause. In Japanese, emmental would correspond to the -ka that marks the scope of a question and awaits an answer (in this case the numbers 4 and 2). Or, we have control inversion: the argument to emmental is a sandboxed user process that occasionally requests input. -- Edit this signature at http://www.digitas.harvard.edu/cgi-bin/ken/sig Gordon Brown's special advisors: www.christianaid.org.uk/stoppoverty/climatechange/stories/special_advisers.aspx ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Profiling and Threading: never the twain shall meet
Dougal Stanton wrote: do (hin, hout, herr, ph) - runInteractiveProcess cmd args Nothing Nothing forkIO $ hPutStr hin content hClose hin out - hGetContents hout return (ph, out) which seems to require threading. If I compile without, it will hang indefinitely, I presume deadlocked. Is there a way this can be done without threading? With much sweat, you could write your own timed polling loop and avoid threads, using hPutBufNonBlocking and hGetBufNonBlocking. I don't recommend it, except for fun or self-torture. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser
On Thursday 05 July 2007, Andrew Coppin wrote: Jonathan Cast wrote: On Wednesday 04 July 2007, Andrew Coppin wrote: Anybody have a solution to this? newtype Parser state x y = Parser (forall src. Source src = (state, src x) - (state, src x, y)) ...OK, anybody have a solution that works in Haskell 98? Rank-2 types are perhaps /the/ most common, widely accepted extension to Haskell 98, after the approved addendum for FFI and the draft addendum for hierarchical modules. I would really be concerned about using them (it's certainly not like they're going to just disappear on you one day, like say functional dependencies almost certainly will). But that's just me. Definition of monad functions, etc, works exactly as for your version. Not so. In fact, doing this causes all mannar of malfunctions. First I get lots of messages of the form Cannot (yet) use update syntax on non-Haskell98 types. Then I get lots of Cannot use function 'foo' as a selector. And then I get My brain has exploded. I can't handle pattern bindings in existentially-quantified type constructors. (?!) And after that I get Type variable 'bar' escapes pattern binding. And finally, after I correct all of those, I get an error saying that the compiler can't match [the hidden type variable] against [some suitable type for that variable]. And in a pattern of all things! (Surely if it's not the right type at runtime, it should generate an exception, just like if you use the wrong constructor...?) Just a side point but: how would it know? Leaving aside the dictionary-passing used for type classes, Haskell has (and has always had) a type-erasure semantics, which rules out runtime type errors. In all, the whole thing just malfunctions horribly and I can get no useful work done! _ So my next plan was to write the code as normal, and then create a front-end module which hides all the messy types. But then I just get a whole bunch of escaping type variable errors again. Basically everything I tried make the code drastically more complicated, and even *then* certain parts of it (most especially the stack function) wouldn't compile. So *neeer* :-P My first thought is that surely you must have said newtype Parser state x y = forall src. Source src = Parser ((state, src x) - (state, src x, y)) when you meant newtype Parser state x y = Parser (forall src. Source src = (state, src x) - (state, src x, y)) The relative order of the constructor name and the forall is very important! If you got the answer right, I can't see why you'd be getting unmistakable existential-type errors; there are no existential quantifiers in my proposal. But I'll try to implement it myself and see what I get. Jonathan Cast http://sourceforge.net/projects/fid-core http://sourceforge.net/projects/fid-emacs ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser
Andrew: By the way, could you share your definition of Stack with us? It isn't at all clear to me how stacked actually decides to terminate the underlying parser. Jonathan Cast http://sourceforge.net/projects/fid-core http://sourceforge.net/projects/fid-emacs ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser
Jonathan Cast wrote: On Thursday 05 July 2007, Andrew Coppin wrote: ...OK, anybody have a solution that works in Haskell 98? Rank-2 types are perhaps /the/ most common, widely accepted extension to Haskell 98, after the approved addendum for FFI and the draft addendum for hierarchical modules. I would really be concerned about using them (it's certainly not like they're going to just disappear on you one day, like say functional dependencies almost certainly will). But that's just me. Personally, I just try to avoid *all* language extensions - mainly because most of them are utterly incomprehensible. (But then, perhaps that's just because they all cover extremely rare edge cases?) MPTCs and ATs look useful. The rest... hmm. If I ever figure out what they do, maybe I can comment. And finally, after I correct all of those, I get an error saying that the compiler can't match [the hidden type variable] against [some suitable type for that variable]. And in a pattern of all things! (Surely if it's not the right type at runtime, it should generate an exception, just like if you use the wrong constructor...?) Just a side point but: how would it know? Leaving aside the dictionary-passing used for type classes, Haskell has (and has always had) a type-erasure semantics, which rules out runtime type errors. Usually if you have something like let (Foo x) = process x y z and it turns out that the 'process' function returns another constructor, you get an error. Well you'd expect the same thing to happen if the result type happens to be a 'hidden' type. But apparently not... So *neeer* :-P My first thought is that surely you must have said newtype Parser state x y = forall src. Source src = Parser ((state, src x) - (state, src x, y)) when you meant newtype Parser state x y = Parser (forall src. Source src = (state, src x) - (state, src x, y)) The relative order of the constructor name and the forall is very important! Care to explain what's different about these apparently identical declarations? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser
Jonathan Cast wrote: Andrew: By the way, could you share your definition of Stack with us? It isn't at all clear to me how stacked actually decides to terminate the underlying parser. Yeah, I'll post the complete source here in a little while. I think that's probably the only way anybody is going to be able to help me effectively... (Netiquette: Is 200 lines too big to past in the body of an email?) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
On Jul 5, 2007, at 9:52 AM, Paul Moore wrote: You're changing the problem from finding a Haskell library (which only needs to be installed on the development machine at compile time) to finding a 3rd party utility, which has to be installed at runtime ... Not a good trade-off. The intersection of Linux and Mac OS X is a pretty amazing standard library, that beats any single scripting language. I'd forgotten how dismal Windows is, sorry. Still, if you stick to non-GPL'd licenses, there's no way to build single file deliverables? I'd think someone would have written Unix as a static library, the way e.g. many languages can be embedded in apps. Then only you would have to maintain the Unix tools you want to use, and you'd be done. If no one has, someone who cares about Windows should. Unix rocks. On Jul 5, 2007, at 9:54 AM, Philip Armstrong wrote: Presumably you mean http://macromates.com/ ? Yup. Sorry. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] A very nontrivial parser
AC For the Nth time... The amount of data processed by parser1 needs AC to depend on the amount of data processed by parser2. (The amount AC of data output by each parser is very nontrivially related to the AC amount of data consumed.) What about lazyness? Let parser1 process ALL the data and return chunks of output paired with the amount of data read; then, parser2 have to return it's result paired with the amount of data read, known from parser1, allowing parser3 to know where to start. It doesn't matter that parser1 wouldn't recognize the rest of data, since it wouldn't be fed with it due to lazyness. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Binary serialization, was Re: Abstraction leak
(Bonus points for being able to parse ASN.1 and generate appropriate Haskell datatypes serialization primitives automatically :-) ) I think there's at least an ASN.1 definition in the crypto library. Dominic might be able to enlighten us on that. No bonus points I'm afraid. There is an embryonic ASN.1 library here http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ASN1-0.0.1 You can take an ASN.1 definition such as FooBar {1 2 0 0 6 1} DEFINITIONS ::= BEGIN Journey ::= SEQUENCE { origin IA5String, stop1 [0] IA5String OPTIONAL, stop2 [1] IA5String OPTIONAL, destination IA5String } Odyssey ::= SEQUENCE { start Journey, trip1 [0] Journey OPTIONAL, trip2 [1] Journey OPTIONAL, trip3 [2] Journey OPTIONAL, end Journey } END And then create abstract Haskell representations of the ASN.1 types journey = Journey ::= AbsSeq Universal 16 Implicit [ Regular (Just origin:: (Nothing :@: absIA5String)), Optional (Just stop1:: (Just 0 :@: absIA5String)), Optional (Just stop2:: (Just 1 :@: absIA5String)), Regular (Just destination :: (Nothing :@: absIA5String)) ] odyssey = Odyssey ::= AbsSeq Universal 16 Implicit [ Regular (Just start:: (Nothing :@: journey)), Optional (Just trip1 :: (Just 0 :@: journey)), Optional (Just trip2 :: (Just 1 :@: journey)), Optional (Just trip3 :: (Just 2 :@: journey)), Regular (Just end :: (Nothing :@: journey)) ] The library then allows you to decode BER representations of these types. It's good enough to decode X.509 identity and attribute certificates. There's no encoding routines currently as I didn't need them. I'll try and make some documentation more easily available if I get time at the weekend. I'm working on PER at the moment both encoding and decoding using GADTs. I will extend it at some point for BER but that won't be for some time. I thought I read that someone was working on parsing ASN.1 so I'll try and follow that up (again it will have to be at the weekend). Dominic. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser [Source code]
-- This is probably line-wrapped horribly... module Process ( Source (..), PState (), start, Process (run), get_state, set_state, alt_state, get, eof, pure, count, many, stack ) where class Source src where empty :: src x - Bool fetch :: src x - (x, src x) instance Source [] where empty = null fetch xs = (head xs, tail xs) data PState st src x = PState {state :: st, source :: src x} start :: (Source src) = st - src x - PState st src x start = PState data Process st src x y = Process {run :: PState st src x - (y, PState st src x)} instance (Source src) = Monad (Process st src x) where return x = Process (\ps - (x, ps)) p = f = Process (\ps - let (y, xs) = run p ps in run (f y) xs) get_state :: Process st src x st get_state = Process(\ps - (state ps, ps)) set_state :: st - Process st src x () set_state st = Process (\ps - ((), ps {state = st})) alt_state :: (Source src) = (st - st) - Process st src x () alt_state f = do st - get_state set_state (f st) get :: (Source src) = Process st src x x get = Process (\ps - let (x,xs) = fetch (source ps) in (x, ps {source = xs})) eof :: (Source src) = Process st src x Bool eof = Process (\ps - (empty (source ps), ps)) pure :: (Source src) = (x - y) - Process st src x y pure f = do x - get return (f x) count :: (Source src, Integral n) = n - Process st src x y - Process st src x [y] count 0 _ = return [] count n p = do y - p ys - count (n-1) p return (y:ys) many :: (Source src) = Process st src x y - Process st src x [y] many p = do end - eof if end then return [] else do y - p ys - many p return (y:ys) data Stack st src x y = Stack {pstate :: PState st src x, pro :: Process st src x [y], buffer :: [y]} instance (Source src) = Source (Stack st src x) where empty stack = empty $ source $ pstate stack fetch stack | empty (buffer stack) = let (ys,xs) = run (pro stack) (pstate stack) in fetch (stack {pstate = xs, buffer = ys}) | otherwise= let (y, ys) = fetch (buffer stack) in (y, stack {buffer = ys}) stack :: (Source src0) = st0 - Process st0 src0 x [y] - st1 - Process st1 (Stack st0 src0 x) y z - Process st9 src0 x z stack st0 p0 st1 p1 = Process (\ps - let ps0 = PState {state = st0, source = source ps} ps1 = PState {state = st1, source = src1} src1 = Stack {pstate = ps0, pro = p0, buffer = []} (z, ys) = run p1 ps1 in (z, ps {source = source $ pstate $ source ys}) ) -- If you want something to test with... module AlgoRLE where import Data.List import Process encodeRLE :: (Eq x, Integral n) = [x] - [(n,x)] encodeRLE = map (\xs - (genericLength xs, head xs)) . group decodeRLE :: (Integral n) = [(n,x)] - [x] decodeRLE = concatMap (uncurry genericReplicate) encodeRLEb :: (Integral x) = [x] - [x] encodeRLEb = concatMap work . encodeRLE where work (1,0)= [0,0] work (n,0)= [0,n-1,0] work (n,x) | n 3= [0,n-1,x] | otherwise = genericReplicate n x decodeRLEb :: (Integral x) = [x] - [x] decodeRLEb = concat . fst . run (many decodeRLEb1) . start () decodeRLEb1 :: (Source src, Integral x) = Process st src x [x] decodeRLEb1 = do v - get if v == 0 then do n - get if n == 0 then return [0,0] else do x - get return $ genericReplicate (n+1) x else return [v] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser
On Thursday 05 July 2007, Andrew Coppin wrote: Jonathan Cast wrote: On Thursday 05 July 2007, Andrew Coppin wrote: ...OK, anybody have a solution that works in Haskell 98? Rank-2 types are perhaps /the/ most common, widely accepted extension to Haskell 98, after the approved addendum for FFI and the draft addendum for hierarchical modules. I would really be concerned about using them (it's certainly not like they're going to just disappear on you one day, like say functional dependencies almost certainly will). But that's just me. Personally, I just try to avoid *all* language extensions - mainly because most of them are utterly incomprehensible. Ah, there's your problem :) (But then, perhaps that's just because they all cover extremely rare edge cases?) I wouldn't call rank-2 types extremely rare . . . snip So *neeer* :-P My first thought is that surely you must have said newtype Parser state x y = forall src. Source src = Parser ((state, src x) - (state, src x, y)) when you meant newtype Parser state x y = Parser (forall src. Source src = (state, src x) - (state, src x, y)) The relative order of the constructor name and the forall is very important! Care to explain what's different about these apparently identical declarations? Sure. Given newtype Parser0 state x y = forall src. Source src = Parser0 ((state, src x) - (state, src x, y)) we get Parser0 :: forall src. Source src = ((state, src x) - (state, src x, y)) - Parser0 state x y which type assignment is isomorphic to (note: not legal Haskell!) Parser0 :: (exists src. Source src = (state, src x) - (state, src x, y)) - Parser0 state x y Given newtype Parser1 state x y = Parser1 (forall src. Source src = (state, src x) - (state, src x, y)) we get Parser1 :: (forall src. Source src = (state, src x) - (state, src x, y)) - Parser state x y The key difference is in the quantifier in the type of the constructor's argument. The exists quantifier (on types) is a tupling operator; Parser0 takes three arguments: a type (elided at run time!), an instance for the Source class (not elided at run time!), and a function implementing the parser. The forall quantifier is a function-forming operator; Parser1 takes one argument, which is a function on a type (elided at run time!) and an instance for the Source class (not elided at run time!), yielding a function implementing the parser. Using a (thoroughly invalid Haskell) record syntax, we could write the two versions Parser0 :: { type src :: *, dict :: Source src, fun :: (state, src x) - (state, src x, y)} - Parser0 state x y Parser1 :: ({ type src :: *, dict :: Source src, input :: (state, src x)} - (state, src x, y)) - Parser1 state x y which may make the distinction a bit clearer (or not). Jonathan Cast http://sourceforge.net/projects/fid-core http://sourceforge.net/projects/fid-emacs ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Sparse documentation
Hi Andrew, On Wed, Jul 04, 2007 at 07:26:48PM +0100, Andrew Coppin wrote: Writing documentation for libraries is one way in which ordinary Haskell users can really contribute to the Haskell community. It’s not hard to do (grab the Darcs repo, type away), and it’s widely appreciated. How exactly do I get started? (Obviously I can't write the documentation for the monad transformers - I don't know how they work yet! But I could have a go at splicing all the Parsec goodness into the Haddoc pages...) Get the latest source: darcs get http://darcs.haskell.org/packages/parsec cd parsec Build the Cabal Setup program and configure the package: ghc --make Setup ./Setup configure Then actually update the documentation, in Text/ParserCombinators/... Now run haddock: ./Setup haddock and check that it looks reasonable. Open dist/doc/html/index.html in your web browser and follow the relevant links. It's probably also a good idea to check you haven't broken the code by accident, i.e. test that it still builds: ./Setup build If you are happy then record and send the patch: darcs record darcs send If you think that the patch might be at all contentious then you should follow the library submissions procedure instead of the last step: http://www.haskell.org/haskellwiki/Library_submissions but for just adding brief haddock docs that's probably overkill. Thanks Ian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser [Source code]
On Thursday 05 July 2007, Andrew Coppin wrote: snip This version works (I think). Also, using this syntax may make the distinction between existential constructors and rank-2 constructors a little clearer. *AlgoRLE run decodeRLEb1 $ start () $ encodeRLEb [1, 2, 3] ([1],PState {state = (), source = [2,3]}) --- Process.hs --- {-# LANGUAGE Rank2Types #-} module Process ( Source (..), PState (), start, Process (run), get_state, set_state, alt_state, get, eof, pure, count, many, stack ) where class Source src where empty :: src x - Bool fetch :: src x - (x, src x) instance Source [] where empty = null fetch xs = (head xs, tail xs) data PState st src x = PState {state :: st, source :: src x} deriving (Eq, Ord, Show) start :: (Source src) = st - src x - PState st src x start = PState data Process st x y = Process {run :: forall src. Source src = PState st src x - (y, PState st src x)} instance Monad (Process st x) where return x = Process (\ps - (x, ps)) p = f = Process (\ps - let (y, xs) = run p ps in run (f y) xs) get_state :: Process st x st get_state = Process(\ps - (state ps, ps)) set_state :: st - Process st x () set_state st = Process (\ps - ((), ps {state = st})) alt_state :: (st - st) - Process st x () alt_state f = do st - get_state set_state (f st) get :: Process st x x get = Process (\ps - let (x,xs) = fetch (source ps) in (x, ps {source = xs})) eof :: Process st x Bool eof = Process (\ps - (empty (source ps), ps)) pure :: (x - y) - Process st x y pure f = do x - get return (f x) count :: (Integral n) = n - Process st x y - Process st x [y] count 0 _ = return [] count n p = do y - p ys - count (n-1) p return (y:ys) many :: Process st x y - Process st x [y] many p = do end - eof if end then return [] else do y - p ys - many p return (y:ys) data Stack st src x y = Stack { pstate :: PState st src x, pro :: Process st x [y], buffer :: [y]} instance (Source src) = Source (Stack st src x) where empty stack = empty $ source $ pstate stack fetch stack | empty (buffer stack) = let (ys,xs) = run (pro stack) (pstate stack) in fetch (stack {pstate = xs, buffer = ys}) | otherwise= let (y, ys) = fetch (buffer stack) in (y, stack {buffer = ys}) stack :: st0 - Process st0 x [y] - st1 - Process st1 y z - Process st9 x z stack st0 p0 st1 p1 = Process (\ps - let ps0 = PState {state = st0, source = source ps} ps1 = PState {state = st1, source = src1} src1 = Stack {pstate = ps0, pro = p0, buffer = []} (z, ys) = run p1 ps1 in (z, ps {source = source $ pstate $ source ys}) ) --- AlgoRLE.hs --- module AlgoRLE where import Data.List import Process encodeRLE :: (Eq x, Integral n) = [x] - [(n,x)] encodeRLE = map (\xs - (genericLength xs, head xs)) . group decodeRLE :: (Integral n) = [(n,x)] - [x] decodeRLE = concatMap (uncurry genericReplicate) encodeRLEb :: (Integral x) = [x] - [x] encodeRLEb = concatMap work . encodeRLE where work (1,0)= [0,0] work (n,0)= [0,n-1,0] work (n,x) | n 3= [0,n-1,x] | otherwise = genericReplicate n x decodeRLEb :: (Integral x) = [x] - [x] decodeRLEb = concat . fst . run (many decodeRLEb1) . start () decodeRLEb1 :: (Integral x) = Process st x [x] decodeRLEb1 = do v - get if v == 0 then do n - get if n == 0 then return [0,0] else do x - get return $ genericReplicate (n+1) x else return [v] Jonathan Cast http://sourceforge.net/projects/fid-core http://sourceforge.net/projects/fid-emacs ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] interrupting an accept()ing thread
Hello, cafe! I have the following code (paraphrased): ... forkIO spin ... spin = do (t, _) - accept s -- (*) forkIO $ dealWith t -- (**) spin My problem is that I want to stop spin from another thread. The obvious solution would be to throw it an exception. However, that leaks a socket (t) if the exception arrives between (*) and (**). I could wrap the whole thing in block, but from looking at the source of Network.Socket it seems that accept itself is not exception safe; so no matter what I do, I can't use asynchronous exceptions to make spin exit. (Is this actually true? Should accept be fixed (along with a lot of other library functions)?) Another idea is to sClose s in another thread. This makes accept throw an IO exception, which breaks the loop. Yay! But it introduces another race condition: If a third thread creates a socket between sClose and accept, the underlying file descriptor of s may get reused, leading to silently wrong behavior because accept listens on the wrong socket now. My question is: How can I use accept in a loop so that I can safely stop it from another thread? Lukas ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Binary serialization, was Re: Abstraction leak
p.f.moore: On 05/07/07, Jonathan Cast [EMAIL PROTECTED] wrote: Can't say I agree. I've been learning Python, and have been very un-impressed so far with its library coverage, which I would rate no better than (in terms of the POSIX bindings, worse than) Haskell. It probably depends on your perspective. I've found lots of tasks that would be a simple library call in Python, but which require me to write the code myself in Haskell. Examples: * Send an email Sounds like a job for MissingH? * Parse an ini file Probably have to write your own Parsec-based parser here. * Gzip compress a data stream We have a wonderful library for this! http://hackage.haskell.org/cgi-bin/hackage-scripts/package/zlib-0.3 * Calculate the MD5 checksum of a file In the Crypto library, or use the openssl binding posted a couple of days ago: http://thread.gmane.org/gmane.comp.lang.haskell.cafe/24165/focus=24170 (Of course, I may just not have found the relevant library - that says something about discoverability rather than coverage, I guess). Find more libraries on hackage: http://hackage.haskell.org/packages/archive/pkg-list.html For bindings, Python's Windows bindings (pywin32) are superb, where Haskell's are minimal and unmaintained. Of course, that won't matter to you if you use POSIX... The one thing off the top of my head that Python had was Base64, but that's 20 lines of Haskell tops. Aside from that, nothing. But that's 20 lines of code I don't want to write, and more, I don't know how to write (without looking up the definition of Base64). Having lots of these seemingly trivial helpers available out of the box is what library coverage means to me. (And Python does have lots of these - I don't know how Haskell fares in practice). I'm not trying to start (or fan) a flamewar, but it's interesting how different people's perspectives on libraries can be... -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] reimplementing break (incorrectly) quickcheck p list gives me feedback that it breaks on list, but not what predicate test caused the breakage
I am a total quickcheck noob. Is there a way to find out what predicate test function is, below? Also, is there a way I can ask quickcheck to test lists of various built in types, not just Int? *** Falsifiable, after 4 tests: function [1] *Recursion testMyBreak Falsifiable, after 1 tests: function [-1,1,2] *Recursion testMyBreak= quickCheck $ \p l - myBreak p (l :: [Int]) == break p l myBreak t xs = let f t next rest = if t next then ([], snd rest) else (next : fst rest, snd rest) in foldr ( f t ) ([],[]) xs --- This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden.___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] interrupting an accept()ing thread
drtomc: On 7/6/07, Lukas Mai [EMAIL PROTECTED] wrote: Hello, cafe! Have you been reading my mind? See the other recent Cafe thread (um, titled something about System.Exit). Here's my solution: ... If you've got small examples illustrating how to use the various concurrency abstractions, feel free to add them to: http://haskell.org/haskellwiki/Concurrency_demos So we can build up a large body of examples for all the libs and tricks out there. -- don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: folds with escapes
Michael Vanier mvanier at cs.caltech.edu writes: I'm sure this has been done a hundred times before, but a simple generalization of foldl just occurred to me and I wonder if there's anything like it in the standard libraries (I couldn't find anything). Basically, I was trying to define the any function in terms of a fold, and my first try was this: any :: (a - Bool) - [a] - Bool any p = foldl (\b x - b || p x) False This is inefficient, because if (p x) is ever True the rest of the list is scanned unnecessarily. So I wrote a more general foldl with an escape predicate which terminates the evaluation, along with a function which tells what to return in that case (given an argument of the running total 'z'): foldle :: (b - Bool) - (a - a) - (a - b - a) - a - [b] - a foldle _ _ _ z [] = z foldle p h f z (x:xs) = if p x then h z else foldle p h f (f z x) xs Using this function, foldl is: foldl' = foldle (const False) id and any is just: any p = foldle p (const True) const False There have already been better responses / solutions to this, but I just wanted to point out that there was already a form of an escaping left fold, namely foldM. import Data.Maybe ( isJust ) import Control.Monad ( foldM ) any p = not . isJust . foldM (\_ x - if p x then Nothing else Just ()) () Of course the logic is a little confusing to read :) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] interrupting an accept()ing thread
On 7/6/07, Lukas Mai [EMAIL PROTECTED] wrote: Hello, cafe! Have you been reading my mind? See the other recent Cafe thread (um, titled something about System.Exit). Here's my solution: acceptLoop sok reqChan = do req - Network.Socket.accept sok atomically (writeTChan reqChan req) acceptLoop sok reqChan mainLoop reqChan quitVar liveOpCountVar = do action - atomically (quitNow `orElse` getReq) case action of Nothing - return () Just (reqSok,reqAddr) - do atomically $ do liveOpCount - readTVar liveOpCountVar writeTVar liveOpCountVar (liveOpCount + 1) forkIO (doSession reqSok reqAddr quitVar liveOpCountVar) mainLoop reqChan quitVar liveOpCountVar where quitNow = do q - readTVar quitVar case q of True - return Nothing False - retry getReq = do req - readTChan reqChan return (Just req) doit sok = do reqChan - atomically newTChan quitVar - atomically (newTVar False) liveOpCountVar - atomically (newTVar 0) forkIO (acceptLoop sok reqChan) mainLoop reqChan quitVar liveOpCountVar atomically $ do liveOpCount - readTVar liveOpCountVar if liveOpCount 0 then retry else return () Although doSession is not included, obviously when you want to quit, something in doSession should set quitVar to True. Also, as suggested elsewhere, doSession should involve a finally clauses to make sure the live op count gets decremented. T. -- Dr Thomas Conway [EMAIL PROTECTED] Silence is the perfectest herald of joy: I were but little happy, if I could say how much. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser
andrewcoppin: Jonathan Cast wrote: On Thursday 05 July 2007, Andrew Coppin wrote: ...OK, anybody have a solution that works in Haskell 98? Rank-2 types are perhaps /the/ most common, widely accepted extension to Haskell 98, after the approved addendum for FFI and the draft addendum for hierarchical modules. I would really be concerned about using them (it's certainly not like they're going to just disappear on you one day, like say functional dependencies almost certainly will). But that's just me. Personally, I just try to avoid *all* language extensions - mainly because most of them are utterly incomprehensible. (But then, perhaps that's just because they all cover extremely rare edge cases?) Some cover edge cases, some are just useful. What about: * the FFI * bang patterns * pattern guards * newtype deriving Surely, fairly simple, useful. Used a lot? :-) -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A very nontrivial parser
On Fri, Jul 06, 2007 at 10:56:43AM +1000, Donald Bruce Stewart wrote: andrewcoppin: Jonathan Cast wrote: On Thursday 05 July 2007, Andrew Coppin wrote: ...OK, anybody have a solution that works in Haskell 98? Rank-2 types are perhaps /the/ most common, widely accepted extension to Haskell 98, after the approved addendum for FFI and the draft addendum for hierarchical modules. I would really be concerned about using them (it's certainly not like they're going to just disappear on you one day, like say functional dependencies almost certainly will). But that's just me. Personally, I just try to avoid *all* language extensions - mainly because most of them are utterly incomprehensible. (But then, perhaps that's just because they all cover extremely rare edge cases?) Some cover edge cases, some are just useful. What about: * the FFI * bang patterns * pattern guards * newtype deriving Surely, fairly simple, useful. Used a lot? :-) How about . in module names? Stefan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] interrupting an accept()ing thread
Am Freitag, 6. Juli 2007 02:13 schrieb Thomas Conway: Here's my solution: acceptLoop sok reqChan = do req - Network.Socket.accept sok atomically (writeTChan reqChan req) acceptLoop sok reqChan mainLoop reqChan quitVar liveOpCountVar = do action - atomically (quitNow `orElse` getReq) case action of Nothing - return () Just (reqSok,reqAddr) - do atomically $ do liveOpCount - readTVar liveOpCountVar writeTVar liveOpCountVar (liveOpCount + 1) forkIO (doSession reqSok reqAddr quitVar liveOpCountVar) mainLoop reqChan quitVar liveOpCountVar where quitNow = do q - readTVar quitVar case q of True - return Nothing False - retry getReq = do req - readTChan reqChan return (Just req) doit sok = do reqChan - atomically newTChan quitVar - atomically (newTVar False) liveOpCountVar - atomically (newTVar 0) forkIO (acceptLoop sok reqChan) mainLoop reqChan quitVar liveOpCountVar atomically $ do liveOpCount - readTVar liveOpCountVar if liveOpCount 0 then retry else return () Although doSession is not included, obviously when you want to quit, something in doSession should set quitVar to True. Also, as suggested elsewhere, doSession should involve a finally clauses to make sure the live op count gets decremented. I don't see how this solves the problem. AFAICS acceptLoop never returns and sok is never closed. On the other hand, my program doesn't need a liveOpCount because the subthreads take care of themselves. It's just the accept loop I need to break somehow. Lukas ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] interrupting an accept()ing thread
On 7/6/07, Lukas Mai [EMAIL PROTECTED] wrote: I don't see how this solves the problem. AFAICS acceptLoop never returns and sok is never closed. On the other hand, my program doesn't need a liveOpCount because the subthreads take care of themselves. It's just the accept loop I need to break somehow. Well, it works because the sub-thread dies when the program exits, so the socket gets closed then. T. -- Dr Thomas Conway [EMAIL PROTECTED] Silence is the perfectest herald of joy: I were but little happy, if I could say how much. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe