[Haskell-cafe] consulting and contracting
I was wondering how many haskell consultants and contractors (ie. freelance programmers) there are and how much demand there is for their work. Also what kind of work do most haskell consultants and contractors get? Is it primarily focused around developing and maintaining haskell compilers and tools? Mostly related to academia? Spread out around several areas? Tim Newsham | www.thenewsh.com/~newsham | thenewsh.blogspot.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Pike's Newsqueak talk
Tim Newsham wrote in article in gmane.comp.lang.haskell.cafe: his language also supports an interesting imperative primitive that lets you pick the first available value from a set of channels which isn't available in pure Haskell expressions. Has anyone implemented a primitive like this for Haskell? Could it be the "amb" described at http://conal.net/blog/posts/functional-concurrency-with-unambiguous-choice/ http://conal.net/blog/posts/smarter-termination-for-thread-racing/ ? It reminds me a little of unamb but is different. Unamb is pure and picks the first computed value of several consistent computations. The select operator picks the first available value from a set of diff channels, some of which may have diff types and so is definitely not pure. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Pike's Newsqueak talk
I just watched http://video.google.com/videoplay?docid=810232012617965344 It's a great talk that is suprisingly relevant to Haskell programming (although at first blush it looks a bit unrelated). (It refs a lot of older work that actually led me to Haskell in the first place by way of McIlroy's haskell power-series paper). Anyway, I thought it would be of general interest. A lot of the progrms he discusses are a lot more elegant in pure Haskell code (ie. prime number sieve, power series), but his language also supports an interesting imperative primitive that lets you pick the first available value from a set of channels which isn't available in pure Haskell expressions. Has anyone implemented a primitive like this for Haskell? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be "too smart"
When you think about it, what you are saying is that Haskell programmers shouldn't take advantage of the extra tools that Haskell provides. No, I'm not saying this. But, as an example, when you read a function like: buildPartitions xs ns = zipWith take ns . init $ scanl (flip drop) xs ns that can be rewritten (argument reversed) as: takeList :: [Int] -> [a] -> [[a]] takeList [] _ = [] takeList _ [] = [] takeList (n : ns) xs = head : takeList ns tail where (head, tail) = splitAt n xs I think this is a perfect example. Haskell allows you to abstract out the concepts of recursion, zipping and iteration. Your alternative reproduces these explicitely and intermixes them. You are saying that programmers should avoid using these higher level abstractions and instead fall back to more explicit constructs that are, for you, easier to read. The problem is that I have still problems at reading and understanding code that is too much terse... Because I have to assemble in my mind each block, and if there are too many blocks I have problems. It takes practice to read and to write. The benefit is more expressiveness and more code reuse. Manlio Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be "too smart"
These friends are very interested in Haskell, but it seems that the main reason why they don't start to seriously learning it, is that when they start reading some code, they feel the "Perl syndrome". That is, code written to be "too smart", and that end up being totally illegible by Haskell novice. I too have this feeling, from time to time. Since someone is starting to write the Haskell coding style, I really suggest him to take this "problem" into strong consideration. When you think about it, what you are saying is that Haskell programmers shouldn't take advantage of the extra tools that Haskell provides. Haskell provides the ability to abstract code beyond what many other programming systems allow. This abstraction gives you the ability to express things much more tersely. This makes the code a lot harder to read for people who are not familiar with the abstractions being used. This can be overcome with practice and experience. I'm not trying to say that code can never get too complex. Humans have some complexity budget and its not too hard to push the limits and blow your complexity budget. But that is true in any language. The ability to abstract lets you factor out common patterns that are easy to reuse and remember (with practice) and lets you spend your complexity budget elsewhere. As a programmer you still need to use your judgement to balance complexity against understandability. [Obviously if you are writing code that you want to be readable by people who arent well versed in common Haskell idioms, you'd limit your use of abstractions.] Manlio Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] symbolic evaluator for Haskell?
Lambdabot (on #haskell) has something similar using a type, Expr, to overload certain names, e.g. koninkje > foldr f z [1..5] lambdabot f 1 (f 2 (f 3 (f 4 (f 5 z It's a complete hack and isn't as sophisticated as what you're after, but it could serve as a basis for implementation ideas. I'm aware of the Expr stuff in lambdabot and elsewhere. This is not quite what I need, perhaps I should have picked an example that doesn't almost-work with Expr. I need something that will symbolically evaluate a complex non-numeric expression that makes use of GADTs. I'm thinking it might not be too hard to implement using TH, but haven't tried yet... (though not sure if TH supports GADTs). Live well, ~wren Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] symbolic evaluator for Haskell?
Is there a symbolic evaluator for Haskell that will perform all applications except on specified functions? Ie. I would love something that would take foldr (+) (6 `div` 5) [1,2,3*4] and "(+) (*)" and return 1 + (2 + (3*4 + 1)) by performing all the applications except for (+) and (*). (Something that supports ghc extensions is preferred :) Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] binary serialization
fft1976: Is there a way to do binary serialization of Haskell values (in GHC, at least)? If you propose a method, what are its type safety and portability properties? There are many ways. See Data.Binary (fast, portable). Most are type safe, or additional safety can be added. I would add to that: Data.Derive can be used to automatically generate Data.Binary.Binary instances for your custom data types. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] monadic MapReduce
How about this. Is there a reason why I can't replace the variables b and c in the type signature of mapReduce with with (IO b') and (IO c'). b and c can be any types. mapReduce :: Strategy (IO b')-- evaluation strategy for mapping -> (a -> IO b') -- map function -> Strategy (IO c')-- evaluation strategy for reduction -> ([IO b'] -> (IO c'))-- reduce function -> [a] -- list to map over -> (IO c') Just remember to wrap all values back in the IO monad. Remember, the idea of map-reduce is to provide a very restrictive programming interface so that you have a lot of flexibility in your execution strategy. If you start loosening the interface you will still be able to execute the program, but you may not be able to perform all the great optimizations you want to perform. For example, if you are using IO actions that are stateful, what are the semantics? Can one map action affect other map actions? Does this imply an ordering of the map functions? Does this imply they all run on the same machine or at least have state communicated between the machines on which they run? The austere interface precludes any of these issues, and therein lies the beauty. Anish Btw. I prefer the sawzall formulation over the map-reduce formulation. A sawzall program just specifies how to map some data to a monoid and the system is free to mappend the monoid values in whatever order it wants (by applying associativity). Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] nubBy changed?
Did nubBy change recently? In 6.8.2 I could generate primes as: nubBy (\a b -> b `mod` a == 0) [2..] but in 6.10.1 I have to use nubBy (\a b -> a `mod` b == 0) [2..] Is this change intentional? If so, what is the reason? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Formal semantics for Haskell?
ML has a formal definition[1]; why not Haskell? Would this be a Good Thing, or a Waste Of Time? Not exactly what you are asking for, but a start: http://www.cs.kent.ac.uk/pubs/1992/123/index.html gregg Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad explanation
So if IO represents a program that when executed interacts with the world's state, is it safe to say that when I return (State Int Int), that I'm returning a "State program"? That'd make sense as it really does look like we force the State to be evaluated with runState, evalState or execState. Yes, exactly. The only difference with IO then is that to get IO programs to run, you have to do it inside another IO program. Almost. Add to your mental model a "runIO" that is invoked when your program runs as: "runIO main". Your haskell compiler or interpretter arranges this for you as part of its contract with you. I hope I'm not making this worse! :-) I dont think so. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad explanation
You are absolutely right. The statement "The values of the IO monad are programs that do IO. " is somewhat nonsensical. Values don't do anything, they just are. But values of the IO monad *describe* how to do IO; they can be seen as a recipe for doing IO. A recipe doesn't cook a dish, but when the recipe is executed by a cook they creates a dish. An IO values doesn't do IO, but when it is executed by the runtime system IO happens. Just as a recipe describes how to cook something, a program describes how to accomplish something. The program doesnt "do" anything until it is executed. However, we often use the word "do" to describe what a program will do when executed (even though its really the cpu that is actually "doing"). This is one way of interpreting what the IO type means. (Another one is to say that Haskell is just an imperative programming language, but any imperative actions show up in the type.) I don't see the difference between these two interpretations. Wether the program is made up of instructions for a cpu or for an interpreter seems irrelevant. -- Lennart Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Monad explanation
I put up a small Monad explanation (I wouldn't quite call it a tutorial): http://www.thenewsh.com/~newsham/haskell/monad.html The intent here is to is to have a short description of what a Monad is that is approachable by Haskell beginners or non- Haskell programmers who are looking for an intuitive definition but may not yet have the background or the inclination to jump into full tutorial to tackle the subject. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Verifying Haskell Programs
State of the art is translating subsets of Haskell to Isabelle, and verifying them. Using model checkers to verify subsets, or extracting Haskell from Agda or Coq. Don, can you give some pointers to literature on this, if any? That is, any documentation of a verification effort of Haskell code with Isabelle, model checkers, or Coq? Graham Hutton's _Programming in Haskell_ has a chapter on reasoning about Haskell code: http://www.cs.nott.ac.uk/~gmh/book.html I put together some exercises of some short proofs for small Haskell functions: http://www.thenewsh.com/~newsham/formal/problems/ I have a short article that covers proofs in Haskell and Isabelle: http://users.lava.net/~newsham/formal/reverse/ The seL4 project is specifying an OS in Haskell, proving it in Isabelle and translating it to C with proofs that connect the translations: http://ertos.nicta.com.au/research/sel4/ I have an article on the curry-howard correspondence http://www.thenewsh.com/~newsham/formal/curryhoward/ In systems like Coq you can write code and proofs of the code in the same language and even at the same time. The Coq'Art book is a good reference, as are Adam Chlipala's draft book and Harvard class materials and the _Type Theory & Functional Programming_ book. Full text for all but Coq'Art are online: http://www.labri.fr/perso/casteran/CoqArt/index.html http://www.cs.harvard.edu/~adamc/cpdt/ http://www.cs.harvard.edu/~adamc/cpdt/book/ http://www.cs.kent.ac.uk/people/staff/sjt/TTFP/ Denis Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell Web Framework
those that want it. From my Django experience, I must say that very few things are cooler than calling a script which automatically generates all the boilerplate code inherent in every web app. Cooler: abstracting away the boilerplate. Michael Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Why monoids will abide...
On Thu, 22 Jan 2009, Eugene Kirpichov wrote: To my mind, in the map-reduce case you generally need a commutative monoid. Or, you need an extra infrastructure that mappend's only results from adjacent machines, or something like that. The paper http://www.cs.vu.nl/~ralf/MapReduce/ analyzes the model of Google's MapReduce and Sawzall. quick haskell summaries at: http://www.thenewsh.com/~newsham/x/machine/MapReduce.hs http://www.thenewsh.com/~newsham/x/machine/Sawzall.hs The MapReduce model isn't based directly on a monoid, but the Sawzall model is. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANN: HTTPbis / HTTP-4000.x package available
There's however still no framework which supports both HTTP client and server functions using the same Request and Response data type, right? I don't know whether I am the only one who needs this (e.g. for the Real Monad Transformer). E.g. a proxy would need this, too. I've wanted this for a while now. "Me Too." Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] software correctness ... can we in FPL step up to the plate??
http://www.businessweek.com/the_thread/techbeat/archives/2009/01/nsa_dhs_industr.html?link_position=link3 ... I think that http://www.galois.com is already doing as stated in the article/ .. I sincerely think there is a segway for Haskell here with strong and static type checking.. Strong static type checking is a very useful tool, but there's a lot more to securing against the 25 most common errors. For example, you can use the type system to ensure that output encoding is always applied to user-provided data, but you must first be aware of this issue and write libraries that enforce this and make use of these libraries a requirement in applications or application frameworks. Some problems such as cross-site request forgery are best addressed by the application framework, so framework authors must be aware of these issues and implement protections for the issue. This usually involves the use of some cryptographic primitives, and the type system doesn't do anything to make sure you get that right. Security issues are (mostly) a subset of correctness issues. Haskell provides some tools to help you make sure your program is correct, but there are a lot of ways to write incorrect software despite the help these tools provide. These tools are very valuable and should be sold to the wider developer community, but they are no silver bullet. Vasili Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Monads aren't evil? I think they are.
I have seen several libraries where all functions of a monad have the monadic result (), e.g. Binary.Put and other writing functions. This is a clear indicator, that the Monad instance is artificial and was only chosen because of the 'do' notation. Maybe that was the initial reason, but I've actually found the Binary.Put.PutM (where Put = PutM ()) to be useful. Sometimes your putter does need to propogate a result... Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Haskell not ready for Foo [was: Re: Hypothetical Haskell job in New York]
Don't get me wrong -- the socket support is pretty decent, but there are also some weird idiosyncrasies, for example requiring that the PortNum is specified in network byte order and lacking a function to convert host->network byte order (hton). PortNum is indeed strange, but it does allow yo to specify the value in your local endian without swapping: > print (toEnum 0x0102 :: PortNumber) 258 what is misleading you is that the obvious construction doesn't: > print (PortNum 0x0102) 513 I'm suprised htonl comes up so often. You can unmarshall data directly from a byte stream to an Int type without caring about the underlying representation of your Int. Why do people want the htonl function? Bardur Arantsson Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell not ready for Foo [was: Re: Hypothetical Haskell job in New York]
On Jan 8, 2009, at 12:56 PM, Tim Newsham wrote: You replied to someone discussing using Haskell at a CDN to implement things like web servers by saying that Haskell wasn't suitable for the task. That is incorrect. I replied to Achim's message asking for elaboration on Haskell's unsuitability. It was a convenient point to discuss Haskell's networking deficiencies. Oops. My apologies. Regards, John Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell not ready for Foo [was: Re: Hypothetical Haskell job in New York]
The number of applications requiring the implementation of a custom web server is an insignificant fraction of the number of applications requiring a messaging system. I don't think anyone would dispute Haskell's ability to do low-level, raw networking, of the type that few people actually need to do. It's the higher level stuff where there's a huge amount of room for improvement. You replied to someone discussing using Haskell at a CDN to implement things like web servers by saying that Haskell wasn't suitable for the task. John Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell not ready for Foo [was: Re: Hypothetical Haskell job in New York]
Take, for example, RabbitMQ. There's nothing even remotely close in Haskell-land. That would be useful for systems that require an "enterprise messaging system," I agree, but I don't see how that would be terribly important for a web server or most other networking services I might want to implement. John Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] data declarations should provide fold functions
I've had to use some fold functions recently and I've come to the conclusion that Haskell should automatically generate fold functions for data definitions. To clarify what I mean, for the data definition: data MyData = This Int Char | That String Int Int there should be a matching function definition: foldMyData f g (This a b) = f a b foldMyData f g (That a b c) = g a b c This definition is as natural as the constructors "This" and "That". Consider the tuple definition and its fold: data (,) a b = (a, b) foldTuple f (x, y) = f x y and the definition of Either and its fold: data Either a b = Left a | Right b foldEither f g (Left x) = f a foldEither f g (Right x) = g x In logic these constructors define the introduction rules ((,), Left and Right) and the folds define the elimination rules (exactly for Either, indirectly for tuples) for conjunction and disjunction. Further, while pattern-matching is very convenient for accessing the constituents of the data type, patterns are not first-class objects in Haskell. Fold functions, on the othe hand, are. They can be passed around and used in higher-order functions to extract constituents in a points-free manner. I know the short-term answer is "use TH" to derive folds if I want them, but I think such an important concept should probably be part of the language. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Coroutines
Andrew was recently asking about co-routines. A couple of years ago, I was in much the same position as him; although I am pretty sure I had heard the term before, it seemed like a mysterious idea with no practical use. Besides the point that people have already made that lazy evaluation gives you similar control as coroutines, I wanted to point out how simple it is to implement coroutines. Here's a simple implementation that ddarius made on IRC a few months back off-the-cuff. I kept it around on codepad because its cool: http://codepad.org/GwtS6wMj -- ryan Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Crash!
Haskell programs with particular constraints (i.e. pure, total Haskell, doesn't primarily call gtk...) Yup, and that's a great thing that we should be evangelizing to all potential users. No need to go overboard and tell them that there will never be a crash, though.. The robustness claim is strong enough without embellishment. -- Don Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Crash!
The point is... I'm not doing that. Gtk2hs is, but that's a well-tested library, so I very much doubt it's the source of the bug. I don't understand why Haskell users believe (perhaps are too often led to believe) that haskell programs can't crash. Gtk2hs does a lot of native stuff. Gtk's been around for a long time, but so has a lot of other software that has lots of bugs still present in it. Often these bugs lead to memory corruption and crashes. Haskell does nothing to prevent this from happening (how could it?). I entirely expect that this crash is due to Gtk2hs (well-tested though it may be) or one of its underlying dependencies (such as libpng). Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] synchronous channels in STM
I was wondering if it was possible to implement synchronous channels within STM. In particular, I'd like to have CSP-like send and recv primitives on a channel that each block until the other side arrives to complete the transaction. I think I've convinced myself that it's not possible, but anyone care to differ? Not quite the same thing, but you can implement synchronous message passing fairly easily with MVars. Here's a small example that builds coroutines, courtesy of ddarius: http://codepad.org/GwtS6wMj you could modify this slightly to have the receiver release the sender as soon as the message is received, if that's what you wanted. Is this close enough for you, or does it have to be in STM? cheers, rog. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] TH code for deriving Binary and NFData instances
Here's some TH code for automatically deriving Data.Binary and Control.Parallel.Strategies.NFData instances: http://www.thenewsh.com/~newsham/store/DeriveBinary.hs Saizan pointed me to: http://www-users.cs.york.ac.uk/~ndm/derive/ which does most of what DeriveBinary.hs does (and lots more). Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] TH code for deriving Binary and NFData instances
Here's some TH code for automatically deriving Data.Binary and Control.Parallel.Strategies.NFData instances: http://www.thenewsh.com/~newsham/store/DeriveBinary.hs Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] TH error
I'm goofing with TH and I have my program mostly done: http://hpaste.org/10713 If I have the "$(deriveBinary ''MyData)" line commented out it prints out what looks to me like correct code. I can even paste it into a program and it compiles. However, when the line isn't commented out I get an error I don't understand: test.hs:1:0: Illegal data constructor name: `x' When splicing generated code into the program There are two places in my code I use "x" in splices that could be causing the problem: g <- [| getWord8 >>= \x -> $(caseE [| x |] gcases') |] and put x = $(caseE [| x |] (map return ps)) |] but I don't understand why these might be causing errors (if they are indeed the cause). Using -ddump-splices doesn't help since it seems to hit the error before dumping splices. What's going on here? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] haskell shootout -- mandelbrot
Here's a whack at regex-dna: http://haskell.org/haskellwiki/Shootout/Parallel/RegexDNA only modest speedup (memory bw bound?). A regex engine that could run several machines concurrently in one pass would prob be a big win. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] haskell shootout -- mandelbrot
a) have you submitted it to the shootout. no b) is it faster yes c) can you put it on the parallel shootout wiki, http://haskell.org/haskellwiki/Shootout/Parallel http://haskell.org/haskellwiki/Shootout/Parallel/Mandelbrot Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] haskell shootout -- mandelbrot
Since this one's trivially parallizable, I took a crack at the mandelbrot test case. It was fairly easy to thread it on a per-line basis in Haskell without changing the original too much. It might be more efficient to break the work into larger chunks, but that would require some slightly more complicated changes so I didn't try that yet. Anyway, the code and the results are here. See README for details: http://www.thenewsh.com/~newsham/shootout/ Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Functional references
Tim Newsham's approach with invertible functions is interesting, though it feels like it's another layer wrapped on top of the primitive idea of functional references. Not all of the refs are using invertible functions.. however, the ones that are invertible are more flexible.. you can use them to make functional references that are mapped over lists, for example. I've reformulated my code a few times since initially posting it.. In the latest incarnation, FRefGen (generic FRefs with arbitrary get/modify) and Inv (invertible functions) are both instances of an FRef class. In earlier versions I had a function for converting an invertible into an FRef. ~wren Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Functional references
It's especially bad when modules are extremely likely to be used together, like Control.Monad.State & FRef, or Data.Map & the Prelude. You end up being required to import one or the other qualified. I think in the case of State vs. FRef a simple solution is to make two modules: FRef, which uses "get" and "set" and "modify" naturally, and FRef.State which defines State equivalents without polluting the namespace. Then if you're working with pure functions you can import FRef and use the natural names, and when you're using the State monad you can import FRef.State and get the State definitions that dont interfere with the standard "get" and "modify" names. In the rare case (I think, am I wrong?) where you use both State and FRef "modify" and "get" definitions in the same file, you can import the one you use less off qualified... -- ryan Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Functional references
I'm playing with functional references and looking for some feedback on a small FRec library I put together: http://www.thenewsh.com/~newsham/FRef.hs Novel (I think) is that the library is applied to some data accesses that are not normally covered by functional references -- ie. extracting words or replacing words in a string or values in an association list. I'm hoping it will provides a useful framework for editing complex values such as data embedded in Base64 cookies in an HTTP header. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell Propeganda
GNU ld supports "pragmas" which cause the use of certain functions to output warnings at link time (try compiling a C program that uses gets()). It occurs to me that this, either in compiler or linker, would be a nice thing for ghc to do when using fromJust or other partial functions. would you include all partial functions in this, such as head? brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [EMAIL PROTECTED] Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] contributing to standard library
Like everyone else who has used Haskell for a while, I'm accumulating functions which I feel should have already been in the standard libraries. What's the normal path to contributing functions for consideration in future standard libraries? Is there some experimental standard lib that we can contribute to to "try out" for the big league? Here are some functions: http://www.thenewsh.com/%7Enewsham/x/machine/Missing.hs Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell Propeganda
As a day-time java programmer, I can say from experience that sometimes (100% pure) Java programs DO segfault. I've had it happen to me, and while you can justifiably say it's an error in the JVM somehow triggered by your program behaviour/timing, that doesn't help you very much at the time. Sure, and just as java has its runtime, so does Haskell. Runtimes are software and prone to being buggy. Runtimes are often written in languages like C where bugs can lead to memory corruption, crashes and arbitrary malicious code execution. Here's a small example that I unfortunately ran across today: ghc -c wxdirect/src/CompileClassTypes.hs -o dist/wxdirect/CompileClassTypes.o -idist/wxdirect -odir dist/wxdirect -hidir dist/wxdirect -package parsec -cpp -package time Segmentation fault (core dumped) :( Maarten Hazewinkel The point being that Haskell, while having a theorem checker that helps programmers find and avoid bugs and while being based on semi-formal concepts that can be used to avoid some pitfalls, is still no silver bullet against any and all crashes. Promising would-be converts that it is will only lead to disappointment. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell Propeganda
I guess I didn't express my point very clearly... That C programmers apparently don't realise that a type system that's sound will give them something -- i.e. their programmer won't ever segfault. I wonder when we try to advertise Haskell if we should be saying "we can give you programs that never segfault", instead of "we have a strong type system". That would be overpromissing. You can definitely get segfaults in Haskell. The obvious example being http://codepad.org/Q8cgS6x8 but many less contrived and more unexpected examples arise naturally (unfortunately). By the way, the Java camp has (correctly) been touting this argument for quite a while. Bob Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] FRP question
I'm interested in FRP, have read several of the papers and am wondering if it could be applied to writing multi-client server programs. What would be the input type events for such a system? What would be the output type events? How would the system handle the fact that it has to multiplex several IO streams (sockets)? I'm trying to answer these questions myself and having a hard time. Should input events include new connection requests and shutdowns? Individual bytes? Streams of bytes? or higher level PDUs? What kind of output should be generated? Full PDUs? streams of bytes? Pairs of (connection identifier,data)? How would such a system effectively hide the multiplexed IO going on? Is this sort of problem poorly suited for FRP? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
Maybe it makes sense to have the streamble list instance in Binary as well, with some examples? Chunk = { length :: Word8 elems :: [Elem] -- 0..255 repetitions } Chunks = [Chunk] -- terminated with the first 0 length Chunk I tried my hand at the encoding above: http://www.thenewsh.com/%7Enewsham/store/test10.hs it seems to work, although it doesn't seem to be very efficient. I'm getting very large memory growth when I was hoping it would be lazy and memory efficient... What's leaking? -- Don Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
I think he might be saying that decodeFile is not the place for application code, because the lower level cannot possibly know whether it makes sense for there to be residual data in the ByteString. There are plenty of file formats that consist of back-to-back concatenated chunks of data, in which reading just one chunk does not by any means require that a file can only contain one. Right, but because of the way decodeFile works, whenever you do not have a data type that explicitely checks for EOF in it's Get definition, decodeFile will leak a file handle. There is no way to check that there is residual data, to access it, or to close the file handle. Since this is the normal state of affairs (are there any Get definitions in the current library which check for EOF when done?) I would suggest that this is an API bug. I would suggest that "decodeFile" should check for EOF when done. A second wrapper function "decodePartialFile" could return the unconsumed data, perhaps, for situations when the EOF behavior is not desired, or return some other way for the file to be closed. Additionally, I would suggest that the Data.Binary library provide a combinator for consuming data fully (ie. checking for EOF). ie: fully :: Get a -> Get a fully a = do x <- a e <- isEmpty return $ case e of False -> error "expected EOF" True -> x decodeFully = runGet $ fully get decodeFile fn = decodeFully <$> B.readFile fn to make it easy for developers who do not use the decodeFile primitive to add EOF checking to their marshalling functions. As it currently stands, the most obvious application of the Data.Binary API leads to subtly confusing errors that may go unnoticed for a while. (This would be a fine point for the documentation to address to prevent others from falling in the same hole). I'm currently using definitions like these and (`using` rnf) and have a server that is able to repeatedly read and write the state file. Many thanks to Dons, Brian, Duncan and everyone else who helped me out... Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
So am I understanding you correctly that you believe this is not a bug? That the use Data.Binary.decodeFile function leaks a file descriptor and this is proper behavior? I still don't understand your explanation of how isEmpty can return True without having read to EOF. The ByteString continues to contain more data until an EOF is reached. Doesn't one of return (B.null s && L.null ss) force getContents to read until EOF? On Wed, 13 Aug 2008, Don Stewart wrote: newsham: Ok, surely at least everyone must agree that this is a bug: force :: Word8 -> IO Word8 force x = print x >> return x -- force = return . (`using` rnf) main = do d <- force =<< decodeFile stateFile encodeFile stateFile d where stateFile = "1word32.bin" test8.hs: 1word32.bin: openBinaryFile: resource busy (file is locked) Remember that decodeFile f = liftM decode (L.readFile f) and readFile :: FilePath -> IO ByteString readFile f = openBinaryFile f ReadMode >>= hGetContents where hGetContents sits in a loop, reading chunks, loop = do c <- S.hGetNonBlocking h k if S.null c then do eof <- hIsEOF h if eof then hClose h >> return Empty else hWaitForInput h (-1) >> loop else do cs <- lazyRead return (Chunk c cs) while isEmpty is just, isEmpty :: Get Bool isEmpty = do S s ss _ <- get return (B.null s && L.null ss) That is, it checks the parsed chunk, it doesn't demand any more reading be done. So the only way you're going to get that Handle closed by readFile is to ensure you read till EOF is hit. After you decode, just ask keep asking for bytes till EOF, or close it yourself, decodeFile f = do h <- openFile f ReadMode ss <- L.hGetContents h let e = decode ss rnf e `seq` hClose h or some such, where you can confirm the decoding as taken place. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
Ok, surely at least everyone must agree that this is a bug: force :: Word8 -> IO Word8 force x = print x >> return x -- force = return . (`using` rnf) main = do d <- force =<< decodeFile stateFile encodeFile stateFile d where stateFile = "1word32.bin" test8.hs: 1word32.bin: openBinaryFile: resource busy (file is locked) the built-in Data.Binary.decodeFile function doesn't close its handle when it is done (same reason as my earlier examples). However, I think probably the real blame here should probably go to Data.Binary which doesn't attempt to check that it has consumed all of its input after doing a "decode". If "decode" completes and there is unconsumed data, it should probably raise an error (it already raises errors for premature EOF). There's no reason for it not to, since it does not provide the unconsumed data to the caller when its done, anyway... I would have expected this to fix my problems: binEof :: Get () binEof = do more <- not <$> isEmpty when more $ error "expected EOF" decodeFully :: Binary b => B.ByteString -> b decodeFully = runGet (get << binEof) where a << b = a >>= (\x -> b >> return x) but even when using decodeFully, it still doesn't close the handle. Shouldn't Data.Binary.Get.isEmpty force a file handle close in the case that it returns True? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
Should the file be closed when the last byte is read (in this case its definitely reading all four bytes) or when the first byte after that is read (in this case it probably doesn't attempt to read more than 4 bytes)? I'll answer my own question. Both Prelude.readFile and Data.ByteString.Lazy.Char8.readFile will keep the file open after reading the last byte and close it when trying to read further. Proof: module Main where import Control.Applicative -- import qualified Data.ByteString.Lazy.Char8 as B import Prelude as B stateFile = "1word32.bin" main = do x <- B.take 4 <$> B.readFile stateFile -- x <- B.take 5 <$> B.readFile stateFile print x B.writeFile stateFile x This works for Prelude and ByteString when taking 5 (there are exactly 4 bytes in "1word32.bin") and fail when taking 4. I'm not sure that this behavior is so bad.. there might be some advantages... but it might be nice to have it close after the last byte is read... However, I think probably the real blame here should probably go to Data.Binary which doesn't attempt to check that it has consumed all of its input after doing a "decode". If "decode" completes and there is unconsumed data, it should probably raise an error (it already raises errors for premature EOF). There's no reason for it not to, since it does not provide the unconsumed data to the caller when its done, anyway... Thoughts? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
Ah, that would be a bug in older ByteString implementations, that were a bit incautious about closing handles. This example works for me with bytestring-0.9.1.0 Yup, thank you Don and Duncan for pointing this out. I updated my bytestring library and the test case no longer fails. However, I'm still having problems and not sure why. I was able to distill the problem down to this: $ od -x 1word32.bin 000 05002ca4 $ runhaskell test6.hs loading... saving... test6.hs: 1word32.bin: openFile: resource busy (file is locked) $ cat test6.hs module Main where import Control.Applicative import Control.Parallel.Strategies (rnf, NFData, using) import Data.Binary import qualified Data.ByteString.Lazy.Char8 as B import Data.Word stateFile = "1word32.bin" loadState :: IO Word32 loadState = decode <$> B.readFile stateFile saveState :: Word32 -> IO () saveState db = B.writeFile stateFile $ encode db {- -- Works! loadState = B.readFile stateFile saveState = B.writeFile stateFile -} -- force x = print x >> return x force = return . (`using` rnf) main = do putStrLn "loading..." d <- force =<< loadState putStrLn "saving..." saveState d I tried this both with "print" and "rnf" to the same effect. It looks like there still might be some situations where the file isn't being closed? Should the file be closed when the last byte is read (in this case its definitely reading all four bytes) or when the first byte after that is read (in this case it probably doesn't attempt to read more than 4 bytes)? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
I'm starting to wonder if this isn't an issue with Data.ByteString.Lazy.Char8.{read,write}File. This simple test case fails: module Main where import qualified Data.ByteString.Lazy.Char8 as B main = do print =<< B.readFile "xxx" B.writeFile "xxx" =<< B.readFile "test.hs" If you replace B.readFile with readFile and B.writeFile with writeFile it works properly. ByteString bug? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
You might have to force the last value of the alist that the map gets flattened into, since otherwise there's no guarantee that it will be read. You really, really want to be using rnf for this job, instead of turning your brain into a pretzel shape. *nod* that's my eventual goal but I'd like to make sure I understand what is going on here first and rule out any bugs before I go using some class I'm not that familiar with. I'm starting to wonder if this isn't an issue with Data.ByteString.Lazy.Char8.{read,write}File. I am now printing out the data entirely: d <- decode <$> B.readFile stateFile print d and I still get the same error when I go to writeFile later. There should be no data items in any of my structures that the print statement does not force. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
Doesn't Data.Map.size run in O(1) time? Maybe something like using different encodings for big maps in the default implementation would help? ugh, of course. Ok, so I fixed it to: loadState db = do d <- decode <$> B.readFile stateFile let force = sum $ map (sum . map fromEnum . M.keys) $ M.elems d print force force `seq` atomically $ writeTVar db d (my keys are dates, which are Enum). This should look at every key in every inner map. Shouldn't that be sufficient to force the entire data set (or do I have to touch the fields in the data elements too?). I still get the same error condition. Felipe. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
Maybe it makes sense to have the streamble list instance in Binary as well, with some examples? A flexible format that doesn't sacrifice too much space efficiency would be to encode in chunks of up to 255 elements: Chunk = { length :: Word8 elems :: [Elem] -- 0..255 repetitions } Chunks = [Chunk] -- terminated with the first 0 length Chunk streamable, amortized cost is about 1/256th of the length, and the encoding is much more efficient than the current scheme for short lists (like most strings). Currently a string "foobar" is 8 bytes for length and 7 for the actual string. -- Don Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
On Tue, 12 Aug 2008, Bryan O'Sullivan wrote: On Tue, Aug 12, 2008 at 5:34 PM, Tim Newsham <[EMAIL PROTECTED]> wrote: I tried to force the data with: loadState db = do d <- decode <$> B.readFile stateFile let force = sum $ M.elems $ M.size `fmap` d force `seq` atomically $ writeTVar db d and I get the same error when trying to writeFile after doing a loadState. What happens if you simply print the number of elements in the map? Forcing its spine is all you should need. This is what the sum above does. Its a Map of Maps, so this maps M.size over the outter Map and sums the resulting elements. That should touch every map element, at least. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
Log: savedState.bin: openFile: resource busy (file is locked) this does not occur if the program wasnt loaded. My best guess here is that B.readFile isnt completing and closing the file for some reason. Is there a good way to force this? Lazy IO. So force the result to be evaluated, and then close the handle, or use strict bytestring reading. There is no visible handle. It's all hidden in readFile. I will try forcing the data. I tried to force the data with: loadState db = do d <- decode <$> B.readFile stateFile let force = sum $ M.elems $ M.size `fmap` d force `seq` atomically $ writeTVar db d and I get the same error when trying to writeFile after doing a loadState. -- Don Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] two problems with Data.Binary and Data.ByteString
so that fromAscList's the result of parsing the map as a list, via, instance Binary a => Binary [a] where put l = put (length l) >> mapM_ put l get= do n <- get :: Get Int replicateM n get so that's a length-prefixed list, strictly. Which is possibly where the stack's being consumed. Does just bumping the stack size a bit help? ugh.. length prefix.. I could bump the stack size to fix my immediate situation, but my goal is to have a server with a huge in-memory data set, and my test data so far is quite small. Alternatively, you could consider serialising the Map in some other format (i.e. newtype the list, and serialise that say, in a lazy/chunked encoding). hackery :( but that sounds like the obvious fix. Log: savedState.bin: openFile: resource busy (file is locked) this does not occur if the program wasnt loaded. My best guess here is that B.readFile isnt completing and closing the file for some reason. Is there a good way to force this? Lazy IO. So force the result to be evaluated, and then close the handle, or use strict bytestring reading. There is no visible handle. It's all hidden in readFile. I will try forcing the data. -- Don Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] two problems with Data.Binary and Data.ByteString
I have a program that read in and populated a large data structure and then saved it out with Data.Binary and Data.ByteString.Lazy.Char8: saveState db = B.writeFile stateFile =<< encode <$> atomically (readTVar db) when I go to read this in later I get a stack overflow: loadState db = do d <- decode <$> B.readFile stateFile atomically $ writeTVar db d Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize' to increase it. or from ghci: d <- liftM decode (Data.ByteString.Lazy.Char8.readFile "savedState.bin") :: IO InstrsDb fromList *** Exception: stack overflow The data type I'm storing is a Map (of maps): type DailyDb = M.Map Date Daily type InstrsDb = M.Map String DailyDb What's going on here? Why is the system capable of building and saving the data but not in reading and umarhsalling it? What is the proper way to track down where the exception is happening? Any debugging tips? I also noticed another issue while testing. If my program loads the data at startup by calling loadState then all later calls to saveState give an error: Log: savedState.bin: openFile: resource busy (file is locked) this does not occur if the program wasnt loaded. My best guess here is that B.readFile isnt completing and closing the file for some reason. Is there a good way to force this? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] code review? store server, 220loc.
On Sat, Aug 2, 2008 at 10:13 PM, Tim Newsham <[EMAIL PROTECTED]> wrote: http://www.thenewsh.com/%7Enewsham/store/Server5.hs You should try profiling this. I can see a few possible problems (such as reading String from a socket, instead of a ByteString), but it's difficult to predict what might be causing your code to be so slow. Haskell code ought to be much more competitive with C for an application like this. Profiling didn't turn up anything obvious: http://www.thenewsh.com/~newsham/store/Server9.prof one thing I dont quite understand is that it seems to be crediting more time to "put8" and "get8" than is warranted, perhaps all of the "get" and "put" functions... One suprising result from testing: http://www.thenewsh.com/~newsham/store/TestBin.hs shows that the Data.Binary marshalling is actually very fast, but when I want to add a length field at the start of the buffer it has a huge impact on performance. I've tried several variations without much luck... (also the third test case is very odd in that skipping a conversion to strict bytestring actually makes it slower(!)). soo... I think thats probably one of the things limiting my performance. Another one is probably my need to do two reads (one for length one for the data) for each received record... I think with some trickiness I could get around that (since recv will return only as many bytes as are immediately available) but I don't know that its worth the effort right now Anyway, any thoughts, especially on how to make the bytestring operations faster, would be appreciated. Tim Newsham ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] code review? store server, 220loc.
You should try profiling this. I can see a few possible problems (such as reading String from a socket, instead of a ByteString), but it's difficult to predict what might be causing your code to be so slow. Haskell code ought to be much more competitive with C for an application like this. I haven't tried profiling yet, I should do that (ugh, will prob have to rebuild some libraries I'm using to support that). Anyway, I haven't yet used any ByteString IO functions. I ran some tests when I was starting and it seems that using Handle IO functions was a bit slower than using the Socket IO functions directly. It looks like there are a bunch of Handle IO functions that can return ByteStrings but I don't see any for sockets... Are there any? If not, I suspect it will be a wash switching to Handles and ByteStrings (especially since most of my requests and responses are quite small). I'll write up some tests to see how well those perform.. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] code review? store server, 220loc.
What kind of performance do you actually need? Can your network connection actually sustain the bandwidth of your synthetic benchmarks? This is just an exercise at the moment, so no particular performance goal beyond "how fast can it go". (tested using apache-bench, loopback interface, amd64 @ 2.2GHz) With cached content 450k: with 1 concurrent client: 760 requests per second ~1ms latency 34Mb/s [...] Obviously this is testing with a loopback network. My point is, it's serving at a rather higher rate than most real network connections I could buy (except local ethernet networks). My requests and responses are fairly small, a typical request is 29bytes and a typical response is 58bytes. If you just count these payloads its about 390kB/sec for 4.5kreq/sec and 1.2MB/sec for 13.5kreq/sec (of course its more like double these as the TCP overhead will be about the same size). Anyway, with such small sizes, the performance shouldn't be limited by the bandwidth (I dont think). If this was a back-end storage server, the network probably wouldn't be the limiting factor. Duncan Tim Newsham http://www.thenewsh.com/~newsham/___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] code review? store server, 220loc.
newsham: Anyone interested in critiquing some code? I'm looking for ideas for making it faster and/or simpler: What optimisation and runtime flags did you use (-threaded or not?) currently "ghc -O --make $< -o $@". For some measurements I tried -threaded which seemed to have a slight slowdown and +RTS -N2 at runtime which didnt seem to help. I also ran some tests with multiple clients running concurrently, and it seemed to handle them at approximately the same rate with and without the threaded and RTS flags (on an amd64x2). Those flags should have allowed it to handle two client connections (via forkIO) concurrently, right? [ps: the same web directory has test clients and other versions of the server.] Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] code review? store server, 220loc.
Anyone interested in critiquing some code? I'm looking for ideas for making it faster and/or simpler: http://www.thenewsh.com/%7Enewsham/store/Server5.hs This is an exercise to see how well a server in Haskell would perform. My goals are roughly: - retargetability to other server types (ie. easy to replace request and response structures and business logic). - readability. - performance. My measurements show that a simple dummy server (accept, forkio, recv byte) handles roughly 7500 requests/connects per second, the server/client that do real messages do about 4500 req and connections per second. If all requests are on the same connection one after another it does about 13500 requests/second. For comparisons, a C ping-pong server does about 3600/second if it has to fork for each new connection/request, and about 35000/sec if its all on the same connection. So it seems at least competitive with a forking C server. I havent tested threaded C servers. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] ghc socket weirdness
FreeBSD/7.0 amd64: GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Loading package base ... linking ... done. Prelude> :module +Network Prelude Network> listenOn $ PortNumber 8765 Loading package parsec-2.1.0.0 ... linking ... done. Loading package network-2.1.0.0 ... linking ... done. *** Exception: getAddrInfo: does not exist (servname not supported for ai_socktype) (same error when compiled). Anyone seen this before? I have multiple NICs, could that be confusing listenOn (does it not just bind on 0.0.0.0?) Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Gtk2Hs and GCs
I don't see a way to fetch an existing standard GC from a widget. In other Gtk bindings I usually do this by fetching the widget's style and then grabbing one of the gc's (such as fg_gc[STATE_NORMAL]). In Gtk2Hs docs: http://www.haskell.org/gtk2hs/docs/gtk2hs-docs-0.9.12/Graphics-UI-Gtk-General-Style.html it looks like you can only get Colors, not the whole GC. I can't seem to find any other way short of making a whole new GC (as is done in Gtk2Hs/demos/graphic/Drawing.hs). Am I missing something? Is there a reason the GC's arent retrievable? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] re: very hard to build darcs with win32 ghc-6.8.2!
Here's the wrapup, thanks to those who replied: - the haskell zlib package on hackage no longer requires that zlib (the C library) be prebuilt. It includes sources itself and builds and installs them using Cabal. - the haskell zlib package is not used by darcs. It links against libz.a directly. You do need to have libz.a somehow to build darcs. - the darcs link error with "SleepEx" is caused because it uses "foreign import ccall" when it should use "foreign import stdcall". Fixing the decl in src/win32/System/Posix.hs to stdcall fixes this issue. I still think its odd that ghc's "gcc" is not very useable outside of Cabal, but in this case it has no bearing on the zlib package. If you choose to build "libz.a" (the C library) from sources using this gcc it will be hard, but you could also get it from an external source (such as the prebuilt libcurl library package). Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] very hard to build darcs with win32 ghc-6.8.2!
I built darcs for win32 recently and it was much more difficult than it should be. Probably most of the blame goes to ghc-6.8.2 binary release for win32. Half of the effort is getting the zlib prereq working. Previously to build zlib for win32 ghc I did the following: http://www.haskell.org/pipermail/haskell-cafe/2007-March/023059.html However, now, the gcc binary for ghc-6.8.2 does not work as well as I would like which requires a bit more effort: - It did not automatically add mingw headers during compilation, and to fix this I had to force some extra flags. I built a shell script "xcc": #!/bin/sh GHC=/ghc/ghc-6.8.2 PATH=/c$GHC/gcc-lib:$PATH export PATH /c$GHC/gcc -I $GHC/include -I $GHC/include/mingw \ -I $GHC/gcc-lib/include -L $GHC/gcc-lib "$@" - During linking it did not find crt2.o and adding it to PATH and -L did not help, so I just copied wholesale all of /c/ghc/ghc-6.8.2/gcc-lib into my zlib source directory. - At this point I was able to build with: CC=./xcc ./configure --prefix=/c/ghc/ghc-6.8.2 \ --libdir=/c/ghc/ghc-6.8.2 make make install Why is the gcc in ghc's directory so non-functional? Ok, so with zlib (the C library) installed, the zlib haskell package installs properly. Dependency resolved. Next, to build darcs I had to configure it without libcurl support (or alternately spend time chasing down that dep, pass for now). Using cygwin I ran "./configure" which falsely uses the cygwin gcc for configuration checks, but since gcc is never used directly during the compilation process, that doesn't matter that much. I could have tried the "xcc" trick here again, but didn't bother. I ran into two problems during the build: - -Werror is specified in the GNUMakefile and there are many warnings. I just removed -Werror for now. - During linking it was not able to resolve "SleepEx" from src/win32/System/Posix.hs. I could not figure out what is going on here. I tried adding "-lkernel32" and "-L /ghc/ghc-6.8.2/gcc-lib -Lkernel32" to the Makefile and it still did not work even though /ghc/ghc-6.8.2/gcc-lib/libkernel32.a has [EMAIL PROTECTED] defined(!) Finally I bit the bullet and hacked around this by noticing that mingw headers have _sleep() defined. I replaced the code in Posix.hs with: foreign import ccall "_sleep" c_sleep :: CULong -> IO () sleep :: Integer -> IO CInt sleep n = c_sleep (fromIntegral n) >> return (toEnum $ fromIntegral n) At this point darcs builds and the binary seems to work (so far). I don't know the implication of my sleep hack (which doesn't return the actual time slept). Here's a small test program which uses FFI to SleepEx which I was not able to get working with win32 ghc-6.8.2. -- {-# OPTIONS -fglasgow-exts -fffi #-} module Main where import Foreign.C.Types foreign import ccall "SleepEx" c_SleepEx :: CUInt -> CInt -> IO CInt main = do putStrLn "start" n <- c_SleepEx (2*1000) 1 print n --- So, what is going on with ghc-6.8.2? Why is the gcc so hard to use now? Why can't I get FFI working with standard win32 functions? Why aren't there prebuilt win32 darcs binaries anymore? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] reordering pure bindings in monads
Intuitively it seems like the applicative expression: (++) <$> getLine <*> getLine should represent the same thing as the more traditional liftM2 expressions: do { x <- getLine; y <- getLine; return ((++) x y) } but it seems to me that you cant directly manipulate the first into the second. I get: do x2' <- getLine x1 <- return ((++) x2') x2 <- getLine return (x1 x2) the only way I can get from here to the liftM2 definition is if I treat "x1 <- return ((++) x2')" as "let x1 = (++) x2", and then allow it to be reordered after the second getLine. Then it is straightforward to reduce to the liftM2 expression above. It seems to me that this is a valid transformation if: - no side effects, including pattern match errors, can occur in the let (or x1 <- return ...). - movement doesnt change the dependencies - x1 isnt used between the original line and its new position - there are no new bindings for x2' introduced between the original line and the new line. Did I overlook anything? Do any haskell implementations allow rewrites like these to occur? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] A mini haskell (in 244 lines of python)
For education and fun I wrote a small untyped non-strict lambda calculus evaluator in python. One of the goals was to keep it fairly small and simple, and to do most of the work in the implemented scripting language itself. For that reason, I added macros to allow things like "let" and "letrec" to be defined as syntactic sugar easily outside of the evaluation engine itself. The result is 244 lines of python, a small prelude that implements tuples, lists and the state monad, and some small example scripts. The prelude and scripts are heavily influenced by Haskell, the main differences being a much simpler syntax, lack of pattern matching and lack of a type system. Data structures aren't supported but are implemented fairly easily using lambda expressions as described in http://www.cs.nott.ac.uk/~nhn/TFP2006/Papers/03-JansenKoopmanPlasmeijer-EfficientInterpretation.pdf This is all available at http://www.thenewsh.com/%7Enewsham/lambda/ as extracted package and .tgz. The README file has documentation including small examples. Accompanying scripts provide more complete examples, such as: [WITHLIST [LET from2 (iter (add 1) 2) [LET primes (nubBy (\x \y (eq (mod y x) 0)) from2) (traceList Val (take 10 primes)) ]]] which calculates the first 10 primes. Exercise to the reader: I bet the evaluator could all be written much more compactly in Haskell. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] strange GHC assembler failure
I'm getting a weird build error: [ 9 of 95] Compiling Plugin.Pl.Common ( Plugin/Pl/Common.hs, dist/build/lambdabot/lambdabot-tmp/Plugin/Pl/Common.o ) /tmp/ghc52608_0/ghc52608_0.s: Assembler messages: /tmp/ghc52608_0/ghc52608_0.s:36:0: Error: unassigned file number 1 [... more of these ...] I narrowed this down -- this happens when I add my new library "silc-client" to the "Build-depends:" line in the cabal file even if none of its code is referenced. Removing the dependency makes the error go away. The module I'm referencing is a new one I'm still working on and it makes use of FFI and references external headers and libraries. (I put a copy at http://www.thenewsh.com/~newsham/silc-client.tgz if it helps anyone debug.. this is not release-quality code though). Any idea what is going on here? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] weird behavior with FFI
Am Samstag, 2. Februar 2008 schrieb Tim Newsham: I am working on haskell bindings to C functions using FFI. I have a callback function that returns "IO ()". When I pass in the callback function: I suspect this has to do with printf returning 'undefined' if you use it with an IO type. Something in the code looks at the result and crashes. Your second version is equivalent to printf "foo" >>= \_ -> return (), i.e. it never evaluates printf's result but returns () instead. Fixing the first version would require some changes to Text.Printf, restricting the 'a' in PrintfType (IO a). But the callback function is already of type "IO ()" as mentioned above. HTH, Lukas Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] weird behavior with FFI
I am working on haskell bindings to C functions using FFI. I have a callback function that returns "IO ()". When I pass in the callback function: foo = printf "foo" it crashes (is there an easy way to debug this exception using ghc6.8.2?) bot: SilcClient_d1al: uncaught exception however, if I pass in the callback function: foo = do printf "foo" return () it does not crash. Is this a bug in my bindings? In ghc/ffi? Full code is at: http://www.thenewsh.com/%7Enewsham/silcbot.tgz Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] IO is a bad example for Monads
I haven't been following this thread closely, but would it be rude to suggest that someone who doesn't want to put the effort into learning the (admittedly difficult) concepts that Haskell embodies shouldn't be using the language? Haskell was never intended to be The Next Big Popular Language. It was intended to be a purely functional language for people who want to use purely functional languages and who are willing to learn new concepts if it enables them to program in that style. This is at odds with the notion, popular on this list and other haskell forums, that pure functional programming is the future. Why is it that every time the topic of teaching basic concepts in an easier way comes up there are always two or three replies that say "should we bother? lets filter out the idiots?" These are pointless and counterproductive. Whether or not you like the idea of lesser entities sullying your private, pure, functional programming language, there are going to be a lot more people learning this language, and there will be people trying to make it easier for them to learn it. whatever. That said, of course we should strive to have better teaching materials, but there are a number of good IO/monad tutorials on the web. [...] because it enables us to write programs more effectively (in many cases, at least) than we can in other languages, but the learning curve is steep -- there ain't no such thing as a free lunch. Many of the best resources for learning Haskell are still academic papers published by language researchers. We've still got a long long way to go... Sure there's no shortcut to learning difficult concepts, but right now its more of a nature hike than a freeway... Mike Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] do
Probably one should understand how to use monads before worrying about the do-notation. Here are some references: I don't totally agree. You can teach monads to beginners just fine using the do-notation. Unsuprisingly its very much like teaching monads using bind. You describe a two line do-block as the basic building block for combining two actions into a single action: do { result1 <- act1 expr involving result1 building an act } show that you can nest them (expr can be another do block) do { result1 <- act1 do { result2 <- act2 expr involving result1 and result2 building an act } } and how the do-notation doesn't require you to start a new do-block for nesting of do's and let's do { result1 <- act1 let val1 <- expr resulting in a pure value result2 <- act2 expr involving result1 and result2 building an act } Then you can describe pattern matching and fail... I've had debates about what should be taught, and obviously not everyone agrees, but at the least, its possible and reasonable and understandable to teach do-notation first. Denis Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] binary operator modifiers
liftM2 (/) sum length. Anyway, the closest you can get in Haskell is something like this, using the infix expressions of Ken Shan and Dylan Thurston<http://www.haskell.org/pipermail/haskell-cafe/2002-July/003215.html> Hmm.. that might be decent if you added rules to pretty-print them in lhs2tex. The src code would be slightly messy but the formatted code would be very clean. And it opens the doors for other binop decorators. Interesting idea. I finally get my lhs2tex set up and put together a better example of what I was talking about: http://www.thenewsh.com/%7Enewsham/Hats.pdf Though I don't know if you can coax lhs2tex into accepting something like %format -:liftM2 (+):- = "\widehat{+}" Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Why are OCaml and Haskell being used at these companies?
Functional programming languages are now much more widely used in industry, primarily because they offer substantial productivity improvements (roughly 10x) over C++ and Java and, consequently, are much more cost effective. Do you have any references for this? Dr Jon D Harrop, Flying Frog Consultancy Ltd. http://www.ffconsultancy.com/products/?e Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] generating Maybe
Data.Maybe has functions for processing Maybe's but nothing useful for creating maybe. I think the following would be a very useful addition, a guarded function: guarded :: (a -> Bool) -> (a -> b) -> a -> Maybe b guarded p f x | p x = Just (f x) | otherwise = Nothing such a function in the std libs would make functions like "unfoldr" more attractive -- uses of foldr nearly always encapsulate this notion. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Standalone PNG module?
Peter Verswyvelen wrote: I would like to load 32-bit images (RGB+alpha) for use with GLUT/OpenGL. I know GTK2HS has support for loading images, but does a standalone Haskell (wrapper) module exists for loading images? See the message "PNG files" by Tim Newsham, sent to haskell-cafe on the 30th of october. The code I wrote is onthe wiki at: http://www.haskell.org/haskellwiki/Library/PNG However, it does not load files, it generates files, and monochrome ones at that. Loading files would be slightly harder since you'd have to support (or at least test for) more options, but the format isn't that complicated. Reinier Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Why can't Haskell be faster?
Unfortunately, they replaced line counts with bytes of gzip'ed code -- while the former certainly has its problems, I simply cannot imagine what relevance the latter has (beyond hiding extreme amounts of repetitive boilerplate in certain languages). Sounds pretty fair to me. Programming is a job of compressing a solution set. Excessive boilerplate might mean that you have to type a lot, but doesn't necessarily mean that you have to think a lot. I think the previous line count was skewed in favor of very terse languages like haskell, especially languages that let you put many ideas onto a single line. At the very least there should be a constant factor applied when comparing haskell line counts to python line counts, for example. (python has very strict rules about putting multiple things on the same line). Obviously no simple measure is going to satisfy everyone, but I think the gzip measure is more even handed across a range of languages. It probably more closely aproximates the amount of mental effort and hence time it requires to construct a program (ie. I can whip out a lot of lines of code in python very quickly, but it takes a lot more of them to do the same work as a single, dense, line of haskell code). When we compete against Python and its ilk, we do so for programmer productivity first, and performance second. LOC was a nice measure, and encouraged terser and more idiomatic programs than the current crop of performance-tweaked low-level stuff. The haskell entries to the shootout are very obviously written for speed and not elegance. If you want to do better on the LoC measure, you can definitely do so (at the expense of speed). -k Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] binary operator modifiers
liftM2 (/) sum length. Anyway, the closest you can get in Haskell is something like this, using the infix expressions of Ken Shan and Dylan Thurston<http://www.haskell.org/pipermail/haskell-cafe/2002-July/003215.html> : [] It works (?), but it's pretty ugly and hardly seems worth it, unfortunately. Hmm.. that might be decent if you added rules to pretty-print them in lhs2tex. The src code would be slightly messy but the formatted code would be very clean. And it opens the doors for other binop decorators. Interesting idea. -Brent Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] PNG files
I needed something small for writing out png files and didn't see anything, so I wrote my own. It's not really large or general enough yet to warrant a full package. It wouldn't require much work to support other variant formats, such as color. Png.hs {- A small library for creating monochrome PNG files. This file is placed into the public domain. Dependencies: Zlib. -} module Png (png) where import Data.Array import Data.Bits import Data.List import Data.Word import qualified Codec.Compression.Zlib as Z import qualified Data.ByteString.Lazy as B be8 :: Word8 -> B.ByteString be8 x = B.singleton x be32 :: Word32 -> B.ByteString be32 x = B.pack [fromIntegral (x `shiftR` sh) | sh <- [24,16,8,0]] pack :: String -> B.ByteString pack xs = B.pack $ map (fromIntegral.fromEnum) xs unpack :: B.ByteString -> String unpack xs = map (toEnum.fromIntegral) (B.unpack xs) hdr, iHDR, iDAT, iEND :: B.ByteString hdr = pack "\137\80\78\71\13\10\26\10" iHDR = pack "IHDR" iDAT = pack "IDAT" iEND = pack "IEND" chunk :: B.ByteString -> B.ByteString -> [B.ByteString] chunk tag xs = [be32 (fromIntegral $ B.length xs), dat, be32 (crc dat)] where dat = B.append tag xs -- | Return a monochrome PNG file from a two dimensional bitmap -- stored in a list of lines represented as a list of booleans. png :: [[Bool]] -> String png dat = unpack $ B.concat $ hdr : concat [ihdr, imgdat, iend] where height = fromIntegral $ length dat width = fromIntegral $ length (head dat) ihdr = chunk iHDR (B.concat [ be32 width, be32 height, be8 1, be8 0, be8 0, be8 0, be8 0]) imgdat = chunk iDAT (Z.compress imgbits) imgbits = B.concat $ map scanline dat iend = chunk iEND B.empty scanline :: [Bool] -> B.ByteString scanline dat = 0 `B.cons` bitpack dat bitpack' :: [Bool] -> Word8 -> Word8 -> B.ByteString bitpack' [] n b = if b /= 0x80 then B.singleton n else B.empty bitpack' (x:xs) n b = if b == 1 then v `B.cons` bitpack' xs 0 0x80 else bitpack' xs v (b `shiftR` 1) where v = if x then n else n .|. b bitpack :: [Bool] -> B.ByteString bitpack xs = bitpack' xs 0 0x80 crc :: B.ByteString -> Word32 crc xs = updateCrc 0x xs `xor` 0x updateCrc :: Word32 -> B.ByteString -> Word32 updateCrc = B.foldl' crcStep crcStep :: Word32 -> Word8 -> Word32 crcStep crc ch = (crcTab ! n) `xor` (crc `shiftR` 8) where n = fromIntegral (crc `xor` fromIntegral ch) crcTab :: Array Word8 Word32 crcTab = array (0,255) $ zip [0..255] $ flip map [0..255] (\n -> foldl' (\c k -> if c .&. 1 == 1 then 0xedb88320 `xor` (c `shiftR` 1) else c `shiftR` 1) n [0..7]) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] binary operator modifiers
I would love to have the ability to define binary operator modifiers. For example: f \overline{op} g = liftM2 op f g f \overleftarrow{op} n = liftM2 op f (return n) n \overrightarrow{op} g = liftM2 op (return n) f \widehat{f} x = liftM f x so that for example you could define functions like: (*3) \overline{+} (/2) and 3 \overrightarrow{+} \widehat{read} getContents Obviously you could write this out the long way: liftM2 (3+) $ liftM read getContents or go through the trouble of defining a bunch of binops f <+> g = liftM2 (+) f g n +> g = return n <+> g f <+ n = f <+> return n read' = liftM read (*3) <+> (/2) 3 +> read' getContents but doing this for more than one or two operators gets tedious quickly... Is there any way in Haskell to modify binops in this way and still be able to use them infix? If not, has anyone considered supporting strange syntaxes like this? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] viewing HS files in Firefox
When I try to go to one of the Module.hs files, e.g. on darcs.haskell.org, it now has type HS and Firefox refuses to display it (and only lets me download it). Does anyone know how to make Firefox treat certain file types as others (HS as plain text, in particular)? so that I can browse them with any convenience In Windows what I do is save the file on the desktop when it asks you to save it. Then right-click the file and select "open with" and choose "wordpad" to open it with. Check the box "open with this application every time". Now close it and go back to your browser and click on the file. It should now open up in wordpad each time. At least that is the behavior in IE. Thanks, Isaac Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Tutorial: Curry-Howard Correspondence
I'm fairly new to this and struggling to follow along so I might be a little off base here... I assume you mean then that it is a valid proof because it halts for *some* argument? Suppose I have: thm1 :: (a -> a) -> a thm1 f = let x = f x in x There is no f for which (thm1 f) halts (for the simple reason that _|_ is the only value in every type), so thm1 is not a valid theorem. Now we reify our propositions (as the tutorial does) in a constructor: data Prop a = Prop a thm2 :: (Prop a -> Prop a) -> Prop a thm2 f = Prop undefined fix :: (p -> p) -> p fix f = let x = f x in x instance Show (Prop a) where show f = "(Prop )" *Prop> :t thm2 thm2 :: (Prop a -> Prop a) -> Prop a *Prop> thm2 (fix id) (Prop ) Wow! thm2 halts. Valid proof. We have a "proof" (thm2 (fix id)) of a "theorem" (((Prop a) -> (Prop a)) -> (Prop a)), assuming that can somehow be mapped isomorphically to ((a -> a) -> a), thence to intuitionist logic as ((a => a) => a). The function needs to be total. You seem to be using Haskell to execute a function to see if it terminates as a proof of totality. Is that fair? This approach might work for some simple examples, but if the function doesn't terminate immediately then what? I would assume that proof of totality would be an obligation of the person who constructed the function. Using Haskell to prove termination for some simple cases might be fair (in which case I see your point about avoiding a non-lazy constructor), but it doesn't seem to be very general anyway. If you're relying on the programmer to provide proof of totality, then I don't see the harm in using "Prop a" instead of "a". That "somehow" in the tutorial seems to be an implied isomorphism from Prop a to a, so that proofs about (Prop a) can be interpreted as proofs about a. I hope to have shown that unless without constructors strict in their arguments that this is not valid. My hypothesis was that data Prop a = Prop !a justified this isomorphism. Or am I still just not getting it? That would allow you to use the dynamic property (I observed termination) to verify the static property (the function is total) in some situations, right? But the static property of totality shouldn't rely on evaluation strategy, right? Dan Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Tutorial: Curry-Howard Correspondence
Very clear tutorial indeed. But why isn't propCC shown as Pierce's Law? And Excluded middle is proven on such basis. Simply because I don't know that much about pierce's law. I've seen it mentioned a few times, but I'm not that familiar with it yet and I haven't read a good treatment of it yet. Do you have any pointers to something I could read? Vitaliy. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Tutorial: Curry-Howard Correspondence
Slightly offtopic - I am curious about the use of forall in some type signatures: If you specify the "forall p q" at the top level then the types used internally will use the same "p" and "q". Otherwise the internal types will be new "p"s and "q"s and wont line up with the outer type declaration. subsume :: forall p q r. Prop (p :=> q) -> Prop ((p :/\ q) :== p) subsume pIMPq = equivInj (impInj pq2p) (impInj p2pq) where pq2p :: Prop (p :/\ q) -> Prop p pq2p assumePQ = andElimL assumePQ p2pq :: Prop p -> Prop (p :/\ q) p2pq assumeP = andInj assumeP q where q = impElim assumeP pIMPq There "r" type variable is mentioned, but it does not occur anywhere else in the signature - what's the purpose of this construct? Ahh! "r" is a remnant of earlier iterations where I had carried around the "r" in every CProp from the classical propositions. Then I realized I could just pick any "r" (I picked "()") and avoid having to type "r" everywhere. So its no longer used, and I'll remove it from the code and the paper. Thank you! Krzysztof Kościuszkiewicz Skype: dr.vee, Gadu: 111851, Jabber: [EMAIL PROTECTED] Mobile IRL: +353851383329, Mobile PL: +48783303040 "Simplicity is the ultimate sophistication" -- Leonardo da Vinci Tim Newsham http://www.thenewsh.com/~newsham/___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Tutorial: Curry-Howard Correspondence
A tutorial on the Curry-Howard Correspondence in Haskell: http://www.thenewsh.com/%7Enewsham/formal/curryhoward/ Feedback appreciated. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] haskell-curry, classical logic, excluded middle
Now that that works, one more question. Is it possible to hide the "r" that is attached to every single type? For example to do something like this (which doesn't compile): No answer needed. Duh.. I can just pick "r" to be any type (like "()"). I've got intuitionistic logic and classic logic in haskell types now, using an identical interface/notation (ie. they're swappable for proofs that don't need excluded-middle). The interfaces use infix type names that "read" similarly to their meanings: logic: http://www.thenewsh.com/%7Enewsham/formal/curryhoward/IntLogic.hs http://www.thenewsh.com/%7Enewsham/formal/curryhoward/ClassLogic.hs and example theorems: http://www.thenewsh.com/%7Enewsham/formal/curryhoward/IntTheorems.hs http://www.thenewsh.com/%7Enewsham/formal/curryhoward/ClassTheorems.hs Should this go up on the wiki somewhere? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] haskell-curry, classical logic, excluded middle
On Sun, 14 Oct 2007, Roberto Zunino wrote: (Warning: wild guess follows, I can not completely follow CPS ;-)) Adding a couple of forall's makes it compile: propCC :: ((forall q . p -> Prop r q) -> Prop r p) -> Prop r p func1 :: (forall q . Or r p (Not r p) -> Prop r q) -> Prop r (Or r p (Not r p)) Yup! That did it, thanks! Now that that works, one more question. Is it possible to hide the "r" that is attached to every single type? For example to do something like this (which doesn't compile): data Prop p = Prop (forall r. (p -> r) -> r) run :: Prop p -> (p -> r) -> r run (Prop f) k = f k propCC :: ((forall q. p -> Prop q) -> Prop p) -> Prop p propCC f = Prop (\k -> run (f (\a -> Prop (\k' -> k a))) k) Zun. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] haskell-curry, classical logic, excluded middle
I've been struggling with this for the last day and a half. I'm trying to get some exercise with the type system and with logic by playing with the curry-howard correspondence. I got stuck on the excluded-middle, and I think now I got it almost all the way there, but its still not quite right. Is this error I'm getting (inline at the end) easily fixed, and what exactly is going on? code --- {-# OPTIONS_GHC -fglasgow-exts #-} module Classic where {- Classic logic. (See Intuit.hs first). In this system propositions all take a continuation. This allows us to define the law of the excluded middle. -} import Control.Monad -- propositions are functions taking a continuation. data Prop r p = Prop ((p -> r) -> r) run :: Prop r p -> (p -> r) -> r run (Prop f) k = f k propCC :: ((p -> Prop r q) -> Prop r p) -> Prop r p propCC f = Prop (\k -> run (f (\a -> Prop (\k' -> k a))) k) instance Monad (Prop r) where return p = Prop (\c -> c p) p >>= mkq = Prop (\c -> run p (\r -> run (mkq r) c)) data TRUTH = TRUTH type FALSE r = Not r TRUTH data And r p q = And (Prop r p) (Prop r q) data Or r p q = OrL (Prop r p) | OrR (Prop r q) data Imp r p q = Imp (Prop r p -> Prop r q) data Equiv r p q = Equiv (Prop r p -> Prop r q) (Prop r q -> Prop r p) data Not r p = Not (forall q. (Prop r p -> Prop r q)) -- Truth truth :: Prop r TRUTH truth = return TRUTH -- And-Injection -- P, Q |- P /\ Q andInj :: Prop r p -> Prop r q -> Prop r (And r p q) andInj p q = return (And p q) -- And-Elimination, left and Right -- P /\ Q |- P andElimL :: Prop r (And r p q) -> Prop r p andElimL pq = pq >>= \(And p q) -> p -- P /\ Q |- Q andElimR :: Prop r (And r p q) -> Prop r q andElimR pq = pq >>= \(And p q) -> q -- Or-Injection, left and right -- P |- P \/ Q orInjL :: Prop r p -> Prop r (Or r p q) orInjL p = return (OrL p) -- Q |- P \/ Q orInjR :: Prop r q -> Prop r (Or r p q) orInjR q = return (OrR q) -- Or-Elimination. -- P \/ Q, P -> R, Q -> R |- R orElim :: Prop r (Or r p q) -> (Prop r p -> Prop r s) -> (Prop r q -> Prop r s) -> Prop r s orElim pORq p2r q2r = pORq >>= byCases where byCases (OrL p) = p2r p byCases (OrR q) = q2r q -- Implication-Injection -- (P |- Q) |- P -> Q impInj :: (Prop r p -> Prop r q) -> Prop r (Imp r p q) impInj p2q = return (Imp p2q) -- Implication-elimination (modus ponen) -- P, P -> Q |- Q impElim :: Prop r p -> Prop r (Imp r p q) -> Prop r q impElim p pIMPq = pIMPq >>= \(Imp p2q) -> p2q p -- Equivalence-Injection -- P -> Q, Q -> P |- P = Q equivInj :: Prop r (Imp r p q) -> Prop r (Imp r q p) -> Prop r (Equiv r p q) equivInj pIMPq qIMPp = do (Imp p2q) <- pIMPq (Imp q2p) <- qIMPp return (Equiv p2q q2p) -- Equivalence-Elimination, Left and Right -- P = Q |- P -> Q equivElimL :: Prop r (Equiv r p q) -> Prop r (Imp r p q) equivElimL pEQq = pEQq >>= \(Equiv p2q q2p) -> return (Imp p2q) equivElimR :: Prop r (Equiv r p q) -> Prop r (Imp r q p) equivElimR pEQq = pEQq >>= \(Equiv p2q q2p) -> return (Imp q2p) -- Absurdity -- False |- P absurd :: Prop r (FALSE r) -> Prop r p absurd false = false >>= \(Not true2p) -> true2p truth -- Not-Inj -- (P |- False) |- ~P notInj :: forall r p. (Prop r p -> Prop r (FALSE r)) -> Prop r (Not r p) notInj p2false = return (Not p2any) where p2any :: forall q. Prop r p -> Prop r q p2any assumep = absurd (p2false assumep) -- Not-Elimination -- P, ~P |- Q notElim :: Prop r p -> Prop r (Not r p) -> Prop r q notElim p np = np >>= \(Not p2any) -> p2any p -- Excluded-Middle -- P \/ ~P exclMiddle :: forall r p. Prop r (Or r p (Not r p)) exclMiddle = propCC func1 where func1 :: (Or r p (Not r p) -> Prop r q) -> Prop r (Or r p (Not r p)) -- k :: Or r p (Not r p) -> Prop r q func1 k = return (OrR (return (Not func2))) where func2 :: Prop r p -> Prop r q func2 k' = k (OrL k') {- http://www.cse.ogi.edu/~magnus/mdo-callcc-slides.pdf -- A \/ ~A excmid :: Either a (a -> b) excmid = callcc (\k. Right (\a.k (Left a))) -} {- Classic2.hs:114:27: Couldn't match expected type `q' (a rigid variable) against inferred type `q1' (a rigid variable) `q' is bound by the type signature for `func2' at Classic2.hs:113:44 `q1' is bound by the type signature for `func1' at Classic2.hs:110:45 Expected type: Prop r q Inferred type: Prop r q1 In the expression: k (OrL k') In the definition of `func2': func2 k' = k (OrL k') -} -- False-Elimination -- (~P |- False) |- P Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] New slogan for haskell.org
"Haskell -- You're probably not smart enough to understand it." You are not expected to understand this. http://swtch.com/unix/ Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Fusing foldr's
Just goofing around with arrows and foldr while reading Hutton's excellent paper on folds (http://www.cs.nott.ac.uk/~gmh/fold.pdf). Wondering if this can be done automatically and more generally? module Main where import Control.Arrow import Data.List -- sum and length expressed as foldr. fsum = foldr (\n -> (+n)) 0 flen = foldr (\n -> (+1)) 0 -- compute average using arrows.. -- compute the sum of a list, compute the length, and do a divide. -- this traverses the list twice using two foldrs. avg1 = uncurry (/) . (fsum &&& flen) avg2 = uncurry (/) . (foldr (\n -> (+n)) 0 &&& foldr (\n -> (+1)) 0) -- But the two foldr's can be fused together -- here we're mixing the two foldr constants 0 and 0 to (0,0) -- and we're mixing the two functions (\n -> (+n)) and -- (\n -> (+1)) to (\n -> (+n) *** (+1)). avg3 = uncurry (/) . foldr (\n -> (+n) *** (+1)) (0, 0) main = do print $ avg1 [1,2,3,4] print $ avg2 [1,2,3,4] print $ avg3 [1,2,3,4] Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Extract source code from literate Haskell (LHS) files
This is of course very easy to do manually, but does a command line tool exist for extracting source code from literate Haskell files? something like: sed -e '/^[^>]/d' -e 's/^>//g' < foo.lhs > foo.hs the first expression deletes lines not starting with ">". The second expression removes the ">" at the beginning of each line. or if you prefer to keep the comments: sed -e 's/^[^>]/-- /g' -e 's/^>//g' < foo.lhs > foo.hs the first expression puts "-- " at the start of each line without a ">". Thanks, Peter Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Rewriting filter with foldr
filter f = foldr (\x -> if (f x) then (x:) else id) [] That's one neat solution but it also raises a few questions for me: foldr :: (a -> b -> b) -> b -> [a] -> b yet you've managed to squeeze in a function that takes only one argument. How is this possible without GHCI blowing its top? Someone already explained this so I'll skip it. 2. Could you please explain the role of the identity function (id) in your code? Where's its argument, or is it sort of implicitly noted? For example, is it the case that the second argument is held in reserve and passed to the first function which would take it, hence (x:) and id? How about working through an example? [I'm using notes on the left hand side. a number starting with a colon is a reference to a definition, and a word followed by a close paren ")" is a justification for the step.] 1: filter f = foldr (\x -> if (f x) then (x:) else id) [] 2: foldr k z xs = go xs 3: where go [] = z 4: go (y:ys) = y `k` go ys filter (> 3) [5,2,6] 1) = foldr (\x -> if (> 3) x then (x:) else id) [] [5,2,6] 2) = go [5,2,6] where 5: go [] = [] 6: go (y:ys) = (\x -> if (> 3) x then (x:) else id) y (go ys) 6) = (\x -> if (> 3) x then (x:) else id) 5 (go [2,6]) lambda) = (if (> 3) 5 then (5:) else id) (go [2,6]) if) = (5:) (go [2,6]) 6) = (5:) ((\x -> if (> 3) x then (x:) else id) 2 (go [6])) lambda) = (5:) (if (> 3) 2 then (2:) else id) (go [6])) if) = (5:) (id (go [6])) id) = (5:) (go [6]) 6) = (5:) ((\x -> if (> 3) x then (x:) else id) 6 (go [])) lambda) = (5:) (if (> 3) 6 then (6:) else id) (go [])) if) = (5:) ((6:) (go [])) 5) = (5:) ((6:) []) (6:))= (5:) [6] (5:))= [5, 6] So you can see that its building up a chain of one-argument functions such as: (5:) (id ((6:) [])) before collapsing it down to a list like [5,6] (note to save space, I collapsed the "id" term early. If I left it till longer we would have arrived at the expression above). Many thanks, Paul Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] some simple proof exercises
Here are two small problem sets of proofs of Haskell functions. They are aimed at people who do not have experience writing proofs and are not necessarily well versed in Haskell. Feedback is appreciated. http://www.thenewsh.com/%7Enewsham/formal/problems/set1.html http://www.thenewsh.com/%7Enewsham/formal/problems/set2.html Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] simple parsing (parsec) intro
I wrote a small intro about how to write a parser in haskell. Its basically about parsec and how it works, but its written without directly referencing parsec and aimed towards beginners (basically wrote it for some friends). Any feedback is appreciated. http://www.thenewsh.com/%7Enewsham/formal/parse/parser.lhs Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] IO in HApps handler ?
Subject: IO in HApps handler ? I am trying to add a handler that would run an external command in HApps 0.8.8, and I got a type issue I do not know how to get around.. can we have IO in a handler ? http://www.haskell.org/haskellwiki/HAppS_tutorial#Application "The MACID monad lets you update your state and *schedule* side-effects. To be clear, MACID is not in the IO monad so you cannot execute side effects, you can only schedule them. The framework takes care of making sure they are executed at-least-once (if they can be completed by a deadline you specify)." I don't know the specifics. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Small proof intro
I put together a small intro lesson on proving haskell code using quickcheck, equational reasoning and Isabelle/HOL. Its very elementary, but might be of interest to some people here. http://www.thenewsh.com/%7Enewsham/formal/reverse/ Feedback is appreciated. Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] FreeBSD/amd64 support?
I noticed that there is no official FreeBSD/amd64 port yet, although there's a binary with a working "ghc" but non-working "ghci." Has there been any progress on the amd64 port? Any estimate on when it will be available? Any known workarounds (is it possible to install and run an x86 ghc in FreeBSD/amd64)? Is hardware access holding anyone up? Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] problem with IO, strictness, and "let"
The problem is that you're closing the file twice. When you call any function of the getContents family, you assign to that function the responsibility to close the file, no sooner than it is no longer needed. Don't call hClose yourself, Bad Things will happen. If you close the file, the stream will suddenly end. I believe silent data corruption is worse than a crash :) (currently, hGetContents also truncates on I/O error, but that's much less common and syslog will tell you about it anyway) Why can't hClose be more... um... lazy? Stefan Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Sparse documentation
Is there a particular module you're having trouble with? Or just griping in general? =) How about STM? It would be nice if I didn't have to scan the paper each time I do something with STM. Isn't that the point of having an API reference? -Brent Tim Newsham http://www.thenewsh.com/~newsham/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe