Re: [Haskell-cafe] Line noise
Dan Piponi wrote: I suspect that most of the complaints about line noise stem from this - to beginners Haskell expressions just look like sequences of identifiers with no apparent grammar to bind them together. This was the exact complaint that some people voiced, yes. (The (.) and ($) operators just compound the problem.) Somebody else then came to my rescue and pointed out that everybody says Lisp is unreadable because it has too many brackets - despite the fact that those brackets theoretically make parsing utterly trivial. ;-) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
Mads Lindstrøm wrote: Andrew Coppin wrote: Idiomatic Haskell seems to consist *only* of single-letter variable names. The more abstract (generic) thing gets, the less likely you will be able to find a telling name. And if you cannot find a telling name, you can just as well make it short. And as Haskell is more abstract, we get more short identifiers. E.g. in your earlier sorting function: qsort (x:xs) = ... what would you propose to call the elements? Well, qsort (element : list) would be maximally intuitive, but who's going to implement it like that? ;-) Now of course in C, you'd be forced to write something like list qsort(int x, list xs) which makes it completely unambiguous what these things are - what their type is. But in Haskell, even if you add a type signature: qsort:: (Ord x) = [x] - [x] Nobody is going to realise that [x] means a list. And it's still not clear where : comes from, or... well you can see why people are getting lost! ;-) However, I will grant you that Map k v, could have used longer type variables. But we are not alone with using one letter type variable names http://java.sun.com/javase/6/docs/api/java/util/HashMap.html . And frankly, in this specific case, I think most programmers (Haskell or non-Haskell) will be able to guess what k and v means, when they are standing right after Map. Only if you can figure out that Map means what every other programming language on the face of the Earth calls a dictionary. (This took me a while!) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Climbing up the shootout...
Don Stewart wrote: Thanks to those guys who've submitted parallel programs to the language benchmarks game, we're climbing up the rankings, now in 3rd, and ahead of C :) http://shootout.alioth.debian.org/u64q/benchmark.php?test=alllang=all Yay! This makes me very happy. ;-) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANNOUNCE: citeproc-hs, a Haskell implementation of the Citation Style Language designed for Pandoc
Hi Gwern, On Fri, Sep 19, 2008 at 09:01:46PM -0400, Gwern Branwen wrote: Hi Andrea. So I was looking at the README. Does citeproc-hs only support adding refs from a .xml file when one's written in Pandoc markdown? That is, I don't see how I could take a .lhs file and a .bib file and produce one of the Pandoc-supported outputs. In particular, I'd really like to be able to go .lhs - .wiki, with refs; this would let me convert The Monad Reader articles for haskell.org. as far as I remember Pandoc can deal with literate Haskell. Check here: http://groups.google.com/group/pandoc-discuss/t/aaaf768ab730192 for bibtex databases, you can use Bibutils (check the citeproc-hs homepage for a link): bibutils is a set of utilities for converting from/to MODS to/from many different bibliographic databases. As you know, Pandoc has a mediawiki writer, so, you should be able to use extended markdown with referecnes to produce articles for the wiki. Keep in mind that pandoc latex reader doesn't use citeproc-hs (yet, I'd like to add). Andrea ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
Andrew Coppin wrote: [...] - Variable names such as x and f aren't fabulously helpful to lost programmers trying to find their way. I'm not a fan of cryptic variable names, either, and I try to use descriptive names wherever I can. But in Haskell... - ... you often have variables, which have a scope of far less than a line such as in map (\(x, (_, y)) - (x, y) ... (cleaning intermediate results from a list). - ... things often get very abstract, so that it just feels wrong matching on, say, (socket:sockets) instead of (x:xs). [...] //Stephan -- Früher hieß es ja: Ich denke, also bin ich. Heute weiß man: Es geht auch so. - Dieter Nuhr ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] readFile and closing a file
On Wed, 17 Sep 2008, Mitchell, Neil wrote: I tend to use openFile, hGetContents, hClose - your initial readFile like call should be openFile/hGetContents, which gives you a lazy stream, and on a parse error call hClose. I could use a function like withReadFile :: FilePath - (Handle - IO a) - IO a withReadFile name action = bracket openFile hClose ... Then, if 'action' fails, the file can be properly closed. However, there is still a problem: Say, 'action' is a parser which produces a data structure lazily. Then further processing of that data structure of type 'a' may again stop before completing the whole structure, which would also leave the file open. We have to force users to do all processing within 'action' and to only return strict values. But how to do this? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [m..n] question
Richard A. O'Keefe [EMAIL PROTECTED] writes: Erlang's equivalent of [m..n] is lists:seq(M, N), which is currently defined to raise an exception when N M. In particular, lists:seq(1, N) returns a list of length N when N 0, but not when N = 0. I'm currently arguing that lists:seq(1, 0) should be [], not an exception. Oddly enough, I'm being beaten over the head with Haskell, of all things. In Haskell, The sequence enumFromTo e1 e3 is the list [e1,e1+1,e1+2,...e3]. The list is empty if e1 e3. It is being claimed that the reason for this is that exceptions are problematic in Hasell, so the Haskell designers went out of their way to make this function total whether it made sense or not. I'm pretty sure that's not true. I'd like to be able to say I know, I was there, but although I was there it was so long ago that my memory isn't clear. But it's clearly the case that [5 .. 6] is [5, 6] (length 2) and [5 .. 5] has to be [5] (length 1), so it's not unreasonable to expect that [5, 4] be [] (length 0) -- having the induction extend down to there makes most sense. I'm fairly certain it was arguments about induction and what constituted sensible behaviour rather than our admitted dislike for exceptions that carried the argument. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Climbing up the shootout...
Don Stewart ha scritto: Thanks to those guys who've submitted parallel programs to the language benchmarks game, we're climbing up the rankings, now in 3rd, and ahead of C :) This is cheating, IMHO. Some test comparisons are unfair. The first problem is with the thread-ring benchmark. Haskell uses the concurrent Haskell extension, but all other programs (with some exceptions) uses OS threads. This is unfair, as an example a C program can make use of the GNU threads library, for user space threads), but there is no such program. If I remove the thread-ring bench, then Haskell goes sixth, after Java and OCaml. With parallel programs it is the same: other languages does not have a parallel version. [...] Manlio Perillo ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Climbing up the shootout...
On 22 Sep 2008, at 11:46, Manlio Perillo wrote: Don Stewart ha scritto: Thanks to those guys who've submitted parallel programs to the language benchmarks game, we're climbing up the rankings, now in 3rd, and ahead of C :) This is cheating, IMHO. Some test comparisons are unfair. The first problem is with the thread-ring benchmark. Haskell uses the concurrent Haskell extension, but all other programs (with some exceptions) uses OS threads. This is unfair, as an example a C program can make use of the GNU threads library, for user space threads), but there is no such program. Who said that C *had* to use OS threads? The point of the shootout is to show the relative strengths of the various languages, one of the strengths of Haskell is some excellent lightweight thread support, this is not present in C, so C does badly on the tests that check how well you can deal with small threads. With parallel programs it is the same: other languages does not have a parallel version. Yes, and the new benchmarks are *specifically* designed to test how fast programs are on more recent multi-core hardware, so again, the other languages are welcome to submit parallel versions... It just turns out that Haskell is pretty damn good at doing parallelism. Bob ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
Andrew Coppin [EMAIL PROTECTED] writes: Idiomatic Haskell seems to consist *only* of single-letter variable names. Good thing, too. Well, qsort (element : list) would be maximally intuitive, but who's going to implement it like that? ;-) Why not listElement : restOfList ? The rationale for having long names is that you have too many names, and too large a scope to keep track of them all in your head. Needing long names is a symptom that your code is too complex, and that you should refactor it. The other problem with descriptive names is that it is not automatically checked by the compiler, and thus it often ends up being misleading. Incorrect documentation is worse than no documentation. qsort:: (Ord x) = [x] - [x] Nobody is going to realise that [x] means a list. And C is utterly incomprehensible, since from my Pascal background, I just *know* that curly braces denote comments. Come on, expecting somebody to understand a language without an extremely basic understanding of fundamental syntactical constructs is futile. well you can see why people are getting lost! ;-) Yes, by refusing to adapt to any syntax but the single one they know. Only if you can figure out that Map means what every other programming language on the face of the Earth calls a dictionary. (This took me a while!) Except for where it is called an associative array or hash table? Terminology is inconsistent, Haskell happens to draw more of it from math than from other programming languages. -k -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: ANNOUNCE: protocol-buffers-0.2.9 for Haskell is ready
I am cross-posting this message to several lists. I had learned the trick before the documentation was updated. It seems I have used a very unreliable trick. And the use castToSTUArray suggested alternative is a really poor one since I am not using arrays at all. Who can suggest a way to cast from Float to Word32 and Double to Word64 using ghc? The actual task is that I need to write out the Float as a little endian sequence of four bytes and also be able to read it back in. The writing and reading are done in Put and Get monads to ByteString (from the binary package). The alloca/poke/peek work around I have looks like castWord32ToFloat :: Word32 - Float castWord32ToFloat x = unsafePerformIO $ alloca $ \p - poke p x peek (castPtr p) castFloatToWord32 :: Float - Word32 castFloatToWord32 x = unsafePerformIO $ alloca $ \p - poke p x peek (castPtr p) The unsafeCoerce trick that is no longer working looks like: castWord64ToDouble :: Word64 - Double castWord64ToDouble (W64# w) = D# (unsafeCoerce# w) castDoubleToWord64 :: Double - Word64 castDoubleToWord64 (D# d) = W64# (unsafeCoerce# d) Any ideas? Or is the alloca trick the only way to do this? Chris Ian Lynagh wrote: Hi Chris, On Sun, Sep 21, 2008 at 05:37:33PM +0100, Chris Kuklewicz wrote: Also, I tried two tricks: (D# x) - (W64# x) which works fine (F# x) - (W32# x) which produced garbage, so I had to replace it with alloca/poke/peek. This isn't supported, and I suspect is the cause of the -fasm problems. Please see http://hackage.haskell.org/trac/ghc/ticket/2209 for more details and suggested alternative. Thanks Ian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] RE: readFile and closing a file
On Wed, 17 Sep 2008, Mitchell, Neil wrote: I tend to use openFile, hGetContents, hClose - your initial readFile like call should be openFile/hGetContents, which gives you a lazy stream, and on a parse error call hClose. I could use a function like withReadFile :: FilePath - (Handle - IO a) - IO a withReadFile name action = bracket openFile hClose ... Then, if 'action' fails, the file can be properly closed. However, there is still a problem: Say, 'action' is a parser which produces a data structure lazily. Then further processing of that data structure of type 'a' may again stop before completing the whole structure, which would also leave the file open. We have to force users to do all processing within 'action' and to only return strict values. But how to do this? I used rnf from Control.Parallel.Strategies when dealing with a similar problem. Would it work in your case? To merge discussion from a related thread: IMO, the question is how much should a language/library prevent the user from shooting himself in the foot? The biggest problem with lazy IO, IMO, is that it presents several opportunities to do so. The three biggest causes I've dealt with are handle leaks, insufficiently evaluated data structures, and problems with garbage collection as in the naive 'mean xs = sum xs / length xs' implementation. There are some idioms that can help with the first two cases, namely the 'with*' paradigm and 'rnf', but the third problem requires that the programmer know how stuff works to avoid poor implementations. While that's not bad per se, in some cases I think it's far too easy for the unwitting, or even the slightly distracted, to get caught in traps. I'm facing a design decision ATM related to this. I can use something like lazy bytestrings, in which the chunkiness and laziness is reified into the datastructure, or an Iterator-style fold for consuming data. The advantage of the former approach is that it's well understood by most users and has proven good performance, while on the downside I could see it easily leading to memory exhaustion. I think the problem with lazy bytestrings, in particular, is that the foldChunks is so well hidden from most consumers that it's easy to hold references that prevent consumed chunks from being reclaimed by the GC. When dealing with data in the hundreds of MBs, or GB range, this is a problem. An Enumerator, on the other hand, makes the fold explicit, so users are required to think about the best way to consume data. It's much harder to unintentionally hold references. This is quite appealing. Based on my own tests so far performance is certainly competitive. Assuming a good implementation, handle leaks can also be prevented. On the downside, it's a very poor model if random access is required, and users aren't as familiar with it, in addition to some of the questions Don raises. Back onto the topic at hand - 'action' could be a parser passed into an enumerator. Since it would read strictly, the action could end the read when it has enough data. That's another approach that I think would work with your problem. Well, that's my 2cents. John Lato ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: ANNOUNCE: protocol-buffers-0.2.9 for Haskell is ready
Chris Kuklewicz wrote: Who can suggest a way to cast from Float to Word32 and Double to Word64 using ghc? The actual task is that I need to write out the Float as a little endian sequence of four bytes and also be able to read it back in. The writing and reading are done in Put and Get monads to ByteString (from the binary package). I think alloca-like hacks is really the wrong direction and asking for trouble. You are trying to translate between platform-dependent native floats, and IEEE floats in a specified platform-independent binary format for Google. So use encodeFloat/decodeFloat - fast primitives in GHC - on the native side, and a hand-written Binary instance for the exact format you need on the Google side. My opinion, YMMV. Regards, Yitz ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Climbing up the shootout...
And, though I had never seen it before, the current winner for speed is ATS ( http://www.ats-lang.org/ ) which is dependently-typed functional language. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Climbing up the shootout...
Hello Manlio, Monday, September 22, 2008, 1:46:55 PM, you wrote: This is cheating, IMHO. Some test comparisons are unfair. this overall test is uselles for speed comparison. afair, there are only 2-3 programs whose speed isn't heavily depend on libraries. in DNA test, for example, Tcl (or PHP?) was leader just because it has better regexp library to make things even funnier, this test allows to use libs bundled to compiler, but not 3rd-arty ones. so ghc (not Haskell!) what includes more built-in libs than gcc looks like a leader. of course, noone uses bare ghc or gcc in real world even benchamrks that test pure speed of compiled code are useless because 1) they are imited by RAM speed, not speed of code itself 2) there uis a fashion in Haskell world to write for shootout in the very low-level style, which isn't actually used in real programming and actually understood only by a few wizards developing high-performance haskell code so actually that this shootout shows is that 1) in real world, program speed more depends on libs that on compilers. if you go to compare weak language plus lot of libs with a strong language with a few libs first variant will win (unless you go to reimplement all these libs at your own) 2) highly-optimized Haskell code is only 2-3 times slower than real C code produces by average C programmer. taken into account that such Haskell code is written many times slower than C one and need much more knowledge, Haskell hardly can be compared to C 3) if you need to compare real-world Haskell code with C one, you may look at these papers: An approach to fast arrays in Haskell http://www.cse.unsw.edu.au/~chak/papers/afp-arrays.ps.gz Rewriting Haskell Strings http://www.cse.unsw.edu.au/~dons/papers/fusion.pdf that they call naive approach is real Haskell programs not speeded up by special libs -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: ANNOUNCE: protocol-buffers-0.2.9 for Haskell is ready
Hello Chris, Monday, September 22, 2008, 2:48:16 PM, you wrote: used a very unreliable trick. And the use castToSTUArray suggested alternative is a really poor one since I am not using arrays at all. castToSTUArray does the same as your code, only in ST monad so you can skip unsafePerformIO trick if you dn't know, ST is a subset of IO monad with a limited set of operations guaranteed to not have side-effects. so, cvt x = unsafePerformIO $ do alloca $ \place - do poke place x peek place and cvt x = runST $ do place - newArray (0,1) writeArray place 0 x readArray place 0 generates almost the same code (the only difference is kind of memory allocated) -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
Am Montag, 22. September 2008 08:32 schrieb Andrew Coppin: However, I will grant you that Map k v, could have used longer type variables. But we are not alone with using one letter type variable names http://java.sun.com/javase/6/docs/api/java/util/HashMap.html . And frankly, in this specific case, I think most programmers (Haskell or non-Haskell) will be able to guess what k and v means, when they are standing right after Map. Only if you can figure out that Map means what every other programming language on the face of the Earth calls a dictionary. (This took me a while!) So, when did Java leave the face of the earth? Seriously, I find Map a far clearer term than dictionary and would've had problems grokking the latter. I guess you've just been exposed to the wrong languages for too long. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Munging wiki articles with tagsoup
Hi For no escaping of any characters, or more likely do something like , and conversions. See the docs: http://hackage.haskell.org/packages/archive/tagsoup/0.6/doc/html/Text-HTML-TagSoup-Render.html Well, I did look at that Haddock page, as well as the others. But honestly, just a bare line like 'renderTagsOptions :: RenderOptions - [Tag] - String' doesn't help me - it doesn't tell me that 'that's default behavior, but you can override it thusly'. The lack of sufficient documentation is a bug. I've filed it at: http://code.google.com/p/ndmitchell/issues/detail?id=91 If someone wants to write the documentation and submit a patch, that would be great. Otherwise, I'll fix it at some unknown point in the future. Thanks Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
On Sun, Sep 21, 2008 at 10:04 PM, Claus Reinke [EMAIL PROTECTED] wrote: Once your readers understand your code, you can add the one-liner and ask for applause This should make it HWN's quotes of the week ! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Ropes
That is a good idea! If I implement head, tail, take drop operations, I can use my KMP implementation out of the box... On Sun, Sep 21, 2008 at 11:10, Nicolas Pouillard [EMAIL PROTECTED] wrote: Excerpts from Rafael Gustavo da Cunha Pereira Pinto's message of Sat Sep 20 12:54:26 +0200 2008: I am doing the ICFPC07 task right now, to learn Haskell and tried to use the Sequence, but the final code is too damn slow (a few iterations per minute!). Is your structure a sequence of *Char*s, if so you should consider to use a sequence of strict bytestrings of a given size (chunks). The DNA needs only 2 operations: head (or take) and concat. I am thinking in using ropes for the DNA and sequences for all the rest (patterns, templates and RNA). On Fri, Sep 19, 2008 at 23:15, Ryan Ingram [EMAIL PROTECTED] wrote: I think Data.Sequence uses fingertrees which are pretty fast. I used a handgrown rope-like structure for ICFPC07 but I wish I had known about Sequence; it would have likely just been better. -- ryan 2008/9/19 Rafael Gustavo da Cunha Pereira Pinto [EMAIL PROTECTED]: Hi all, Is there any implementation of the rope data structure in Haskell? I couldn't find any on Hackage, and I am intending to implement it. Regards, Rafael Gustavo da Cunha Pereira Pinto Electronic Engineer, MSc. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Nicolas Pouillard aka Ertai -- Rafael Gustavo da Cunha Pereira Pinto Electronic Engineer, MSc. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] RE: readFile and closing a file
jwlato: On Wed, 17 Sep 2008, Mitchell, Neil wrote: I tend to use openFile, hGetContents, hClose - your initial readFile like call should be openFile/hGetContents, which gives you a lazy stream, and on a parse error call hClose. I could use a function like withReadFile :: FilePath - (Handle - IO a) - IO a withReadFile name action = bracket openFile hClose ... Then, if 'action' fails, the file can be properly closed. However, there is still a problem: Say, 'action' is a parser which produces a data structure lazily. Then further processing of that data structure of type 'a' may again stop before completing the whole structure, which would also leave the file open. We have to force users to do all processing within 'action' and to only return strict values. But how to do this? I used rnf from Control.Parallel.Strategies when dealing with a similar problem. Would it work in your case? To merge discussion from a related thread: IMO, the question is how much should a language/library prevent the user from shooting himself in the foot? The biggest problem with lazy IO, IMO, is that it presents several opportunities to do so. The three biggest causes I've dealt with are handle leaks, insufficiently evaluated data structures, and problems with garbage collection as in the naive 'mean xs = sum xs / length xs' implementation. There are some idioms that can help with the first two cases, namely the 'with*' paradigm and 'rnf', but the third problem requires that the programmer know how stuff works to avoid poor implementations. While that's not bad per se, in some cases I think it's far too easy for the unwitting, or even the slightly distracted, to get caught in traps. I'm facing a design decision ATM related to this. I can use something like lazy bytestrings, in which the chunkiness and laziness is reified into the datastructure, or an Iterator-style fold for consuming data. The advantage of the former approach is that it's well understood by most users and has proven good performance, while on the downside I could see it easily leading to memory exhaustion. I think the problem with lazy bytestrings, in particular, is that the foldChunks is so well hidden from most consumers that it's easy to hold references that prevent consumed chunks from being reclaimed by the GC. When dealing with data in the hundreds of MBs, or GB range, this is a problem. An Enumerator, on the other hand, makes the fold explicit, so users are required to think about the best way to consume data. It's much harder to unintentionally hold references. This is quite appealing. Based on my own tests so far performance is certainly competitive. Assuming a good implementation, handle leaks can also be prevented. On the downside, it's a very poor model if random access is required, and users aren't as familiar with it, in addition to some of the questions Don raises. Yes, I'm certain we can reach the performance of, or outperform, lazy (cache-sized chunk) bytestrings using enumerators on chunks, but the model is somewhat unfamiliar. Structuring the api such that people can write programs in this style will be the challenge. -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Updated formlets sample?
Hi Chris, you're absolutely right. The mistake was in the where-part of withForm. The function handleOk' gets an environment d as argument but uses an extractor that was created without passing d to runFormState. I've put a corrected version on hpaste [1] and also posted it to the wiki on haskell.org [2]. Hope this is ok for you? Regards, Martin. [1] http://hpaste.org/10568#a1 [2] http://haskell.org/haskellwiki/Formlets Chris Eidhof schrieb: That means that you don't have input0 in your environment, maybe you're passing in an empty environment? -chris On 21 sep 2008, at 12:11, Martin Huschenbett wrote: Hi Chris, thanks for the updated example. Compiling works now. But when I try to run it I alway get error messages like [input0 is not in the data,input1 is not in the data] Regards, Martin. Chris Eidhof schrieb: Hey Martin, On 19 sep 2008, at 04:14, Martin Huschenbett wrote: I found a blog post concerning formlets [1] in the web. Since looks very interesting I tried to compile the sample code with recent versions of HAppS and formlets from hackage. But this didn't work as the API of formlets has changed since this post. I tried to adopt the code to the new API but I was unable to finish this since there is a new monadic context I don't know to handle in the right way. So my question is, is there an updated version of this sample code in the web or has anybody tried to adopt it and can send me the results? Yes, I'm sorry for that. The API is still very immature and due to changes, that's also why it hasn't been officially announced yet. I've just put an updated example at http://hpaste.org/10568, hope that'll work for you. I guess we should build a small homepage / wikipage that always has an up-to-date example. -chris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
On Mon, Sep 22, 2008 at 1:50 PM, Daniel Fischer [EMAIL PROTECTED]wrote: Am Montag, 22. September 2008 08:32 schrieb Andrew Coppin: However, I will grant you that Map k v, could have used longer type variables. But we are not alone with using one letter type variable names http://java.sun.com/javase/6/docs/api/java/util/HashMap.html . And frankly, in this specific case, I think most programmers (Haskell or non-Haskell) will be able to guess what k and v means, when they are standing right after Map. Only if you can figure out that Map means what every other programming language on the face of the Earth calls a dictionary. (This took me a while!) So, when did Java leave the face of the earth? At the same time as C++ presumably. I hadn't really noticed, but I'll be the first to say: Good riddance! -- Sebastian Sylvan +44(0)7857-300802 UIN: 44640862 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Climbing up the shootout...
On Mon, Sep 22, 2008 at 2:07 PM, Bulat Ziganshin [EMAIL PROTECTED] wrote: this overall test is uselles for speed comparison. afair, there are only 2-3 programs whose speed isn't heavily depend on libraries. in DNA test, for example, Tcl (or PHP?) was leader just because it has better regexp library On the regex-dna benchmark, I'll have to agree. It's unfortunate to have a benchmark so dependent on the set of libraries included in the distribution, and e.g. Text.Regex.PCRE kicks Text.Regex.Posix's behind in this benchmark - but we probably can't use it only because one's bundled and the other isn't. Maybe we could roll our own regexp engine for this specific benchmark though (for example, Text.Regex.TDFA is within 10% or something of PCRE and AFAIK pure Haskell - a customized and downsized version of that could probably be made quite competitive). to make things even funnier, this test allows to use libs bundled to compiler, but not 3rd-arty ones. so ghc (not Haskell!) what includes more built-in libs than gcc looks like a leader. of course, noone uses bare ghc or gcc in real world I don't think it's ever claimed that the shootout is a fair benchmark of real-world problems :D 2) there uis a fashion in Haskell world to write for shootout in the very low-level style, which isn't actually used in real programming and actually understood only by a few wizards developing high-performance haskell code That is certainly the case with a few of the benchmark implementations, and in the past it was required to get the performance. In some cases it's also due simply to the haskell implementation being a straight-from-C port - which necessitates using pointers and putting everything in IO etc... Some of that haskell code is among the least readable code I've ever read (see e.g. the fannkuch benchmark at http://shootout.alioth.debian.org/u64q/benchmark.php?test=fannkuchlang=ghc). But that's what you get when porting pointer-rich C code directly into Haskell :) With bytestrings, unboxed arrays, light-weight threads and other tricks, we can usually replace all those ugly low-level programs with nice high-level haskell ones - it's all about allowing the compiler to do good stuff with naive (or at least naive-looking) code, and teaching it how to cut through the abstractions. (As well as using the right abstractions, of course...) // Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[4]: [Haskell-cafe] Climbing up the shootout...
Hello Simon, Monday, September 22, 2008, 9:03:52 PM, you wrote: With bytestrings, unboxed arrays, light-weight threads and other tricks, we can usually replace all those ugly low-level programs with nice high-level haskell ones i don't think that these 3 libs allows to write high-level high-performance code in *most* cases. just for example, try to write wc without using words -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] hGetContents and lazyness
Hello, haskellers! Suppose we have function (it filters package filenames from apt Packages file): getPackageList :: FilePath - IO [FilePath] getPackageList packageFile = withFile packageFile ReadMode $ \h - do c - hGetContents h return $ map (drop 10) $ filter (startsWith Filename:) $ lines c -- (1) where startsWith [] _ = True startsWith _ [] = False startsWith (x:xs) (y:ys) | x == y= startsWith xs ys | otherwise = False When, I apply it to a Packages file I (surely) get an empty list. This is an expected result due to lazyness of hGetContents. I tried changing line (1) to return $ map (drop 10) $ filter (startsWith Filename:) $! lines c or return $ map (drop 10) $! filter (startsWith Filename:) $! lines c with no success. Chaning it to return $! map (drop 10) $ filter (startsWith Filename:) $ lines c makes getPackageList function return several (but not all) filenames. What I'm missing? And how can I fix my code? -- WBR, Max Vasin. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Climbing up the shootout...
--- Simon Brenner [EMAIL PROTECTED] wrote: On Mon, Sep 22, 2008 at 2:07 PM, Bulat Ziganshin [EMAIL PROTECTED] wrote: this overall test is uselles for speed comparison. afair, there are only 2-3 programs whose speed isn't heavily depend on libraries. in DNA test, for example, Tcl (or PHP?) was leader just because it has better regexp library On the regex-dna benchmark, I'll have to agree. It's unfortunate to have a benchmark so dependent on the set of libraries included in the distribution, and e.g. Text.Regex.PCRE kicks Text.Regex.Posix's behind in this benchmark - but we probably can't use it only because one's bundled and the other isn't. Maybe we could roll our own regexp engine for this specific benchmark though (for example, Text.Regex.TDFA is within 10% or something of PCRE and AFAIK pure Haskell - a customized and downsized version of that could probably be made quite competitive). You could always suggest use of Text.Regex.PCRE, provide a program and instructions on how to install Text.Regex.PCRE on Ubuntu. -snip- With bytestrings, unboxed arrays, light-weight threads and other tricks, we can usually replace all those ugly low-level programs with nice high-level haskell ones ... Go do! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Climbing up the shootout...
igouy2: --- Simon Brenner [EMAIL PROTECTED] wrote: On Mon, Sep 22, 2008 at 2:07 PM, Bulat Ziganshin [EMAIL PROTECTED] wrote: this overall test is uselles for speed comparison. afair, there are only 2-3 programs whose speed isn't heavily depend on libraries. in DNA test, for example, Tcl (or PHP?) was leader just because it has better regexp library On the regex-dna benchmark, I'll have to agree. It's unfortunate to have a benchmark so dependent on the set of libraries included in the distribution, and e.g. Text.Regex.PCRE kicks Text.Regex.Posix's behind in this benchmark - but we probably can't use it only because one's bundled and the other isn't. Maybe we could roll our own regexp engine for this specific benchmark though (for example, Text.Regex.TDFA is within 10% or something of PCRE and AFAIK pure Haskell - a customized and downsized version of that could probably be made quite competitive). You could always suggest use of Text.Regex.PCRE, provide a program and instructions on how to install Text.Regex.PCRE on Ubuntu. -snip- With bytestrings, unboxed arrays, light-weight threads and other tricks, we can usually replace all those ugly low-level programs with nice high-level haskell ones ... Go do! All is in hand. Tim Newsham's uploaded a regex-pcre and regex-posix entry to the wiki, and I'm testing now on quad core. If it survives testing, we'll submit it to Isaac. -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Fwd: [Haskell-cafe] hGetContents and lazyness
-- Forwarded message -- From: Rafael Gustavo da Cunha Pereira Pinto [EMAIL PROTECTED] Date: Mon, Sep 22, 2008 at 15:46 Subject: Re: [Haskell-cafe] hGetContents and lazyness To: Max Vasin [EMAIL PROTECTED] Why don't you use OpenFile? getPackageList packageFile = do h - OpenFile packageFile ReadMode c - hGetContents h return $ map (drop 10) $ filter (startsWith Filename:) $ lines c I am not at home so I don't have GHC around here, but this usually works for me! Anyway, it also depends on who is consuming the IO [FilePath] data returned. It will not be evaluated unless asked for! On Mon, Sep 22, 2008 at 14:52, Max Vasin [EMAIL PROTECTED] wrote: Hello, haskellers! Suppose we have function (it filters package filenames from apt Packages file): getPackageList :: FilePath - IO [FilePath] getPackageList packageFile = withFile packageFile ReadMode $ \h - do c - hGetContents h return $ map (drop 10) $ filter (startsWith Filename:) $ lines c -- (1) where startsWith [] _ = True startsWith _ [] = False startsWith (x:xs) (y:ys) | x == y= startsWith xs ys | otherwise = False When, I apply it to a Packages file I (surely) get an empty list. This is an expected result due to lazyness of hGetContents. I tried changing line (1) to return $ map (drop 10) $ filter (startsWith Filename:) $! lines c or return $ map (drop 10) $! filter (startsWith Filename:) $! lines c with no success. Chaning it to return $! map (drop 10) $ filter (startsWith Filename:) $ lines c makes getPackageList function return several (but not all) filenames. What I'm missing? And how can I fix my code? -- WBR, Max Vasin. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Rafael Gustavo da Cunha Pereira Pinto Electronic Engineer, MSc. -- Rafael Gustavo da Cunha Pereira Pinto Electronic Engineer, MSc. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
On Sun, Sep 21, 2008 at 1:10 PM, Andrew Coppin [EMAIL PROTECTED] wrote: I posted a snippet of code which included the phrase mapM_ (\(n,v) - putStrLn $ [ ++ show n ++ ] = ++ show v) (zip [0..] vs) To somebody familiar with Haskell, that is as clear as day. But to a newbie... well *you* try explaining that you start at the left end, take the thing in brackets, process it from left to right, then take the other thing in brackets, process the right side of it, then pass that to putStrLn, oh, but that thing right at the left edge is the argument list, and then pass the whole lot to mapM_, which is... are you still with me?? As one experienced C++ programmer put it, there is no clear flow from left to right or right to left. This is actually one of the two main metrics I use when I'm writing code -- I try to keep the information content in my code local, so you don't have to scan across the screen to see what n corresponds to. This is equivalent to maintaining a left-to-right or right-to-left flow (and really which direction it is depends more on reading style than writing style). The other one I picked up from Perl of all places, and that is end weight. In English we tend to put the important parts (the essence) of the sentence at the front, and leave the details for the end. So I like to emulate that in Haskell when I can. There is little I loathe more than the style: map (\x - ... ... ... ... ...) xs As such, the probability that I would have written the mapM_ line above is very low, since it violates both of these. In this case, switching to forM_ brings it much closer to my style: forM_ (zip [0..] vs) $ \(n,v) - putStrLn $ [ ++ show n ++ ] = ++ show v That is because the details of this sentence are in the function, so I put it at the end. Also the corresponding [0..] and n are close together, as are the corresponding vs and v. Luke ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[4]: [Haskell-cafe] Climbing up the shootout...
On Mon, Sep 22, 2008 at 1:12 PM, Bulat Ziganshin [EMAIL PROTECTED] wrote: Hello Simon, Monday, September 22, 2008, 9:03:52 PM, you wrote: With bytestrings, unboxed arrays, light-weight threads and other tricks, we can usually replace all those ugly low-level programs with nice high-level haskell ones i don't think that these 3 libs allows to write high-level high-performance code in *most* cases. just for example, try to write wc without using words. To a newbie, that's a cryptic statement. Are you saying that these libs aren't needed to make a high-performance wc, and that the Prelude functions are sufficient? (I note too that there is Data.ByteString.Char8.words, but I assume you are talking about the Prelude function.) Graham ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[6]: [Haskell-cafe] Climbing up the shootout...
Hello Graham, i don't think that these 3 libs allows to write high-level high-performance code in *most* cases. just for example, try to write wc without using words. To a newbie, that's a cryptic statement. Are you saying that these libs aren't needed to make a high-performance wc, and that the Prelude functions are sufficient? (I note too that there is Data.ByteString.Char8.words, but I assume you are talking about the Prelude function.) i mean that naive haskell code is very slow and 3 or 5 or twelve libs can't solve the problem of ghc generating slow code -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Line noise
Hello Luke, Monday, September 22, 2008, 11:00:12 PM, you wrote: mapM_ (\(n,v) - putStrLn $ [ ++ show n ++ ] = ++ show v) (zip [0..] vs) forM_ (zip [0..] vs) $ \(n,v) - putStrLn $ [ ++ show n ++ ] = ++ show v for (zip [0..] vs) $ \(n,v) - do putStrLn $ [ ++ show n ++ ] = ++ show v ... it's rather close to C/Pascal/... loops although it will be great to have more sugar here -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] hGetContents and lazyness
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Max Vasin wrote: Hello, haskellers! Suppose we have function (it filters package filenames from apt Packages file): getPackageList :: FilePath - IO [FilePath] getPackageList packageFile = withFile packageFile ReadMode $ \h - do c - hGetContents h return $ map (drop 10) $ filter (startsWith Filename:) $ lines c -- (1) where startsWith [] _ = True startsWith _ [] = False startsWith (x:xs) (y:ys) | x == y= startsWith xs ys | otherwise = False When, I apply it to a Packages file I (surely) get an empty list. This is an expected result due to lazyness of hGetContents. Combined with the fact that you're not evaluating its non-strict result until after the file handle has been closed, yes. Your current set of IO actions is probably similar to: . open file . process file . close file . use results from processing the file. where the first three steps are all handled by your getPackageList. To avoid either getting incomplete (or empty) results, or having to strictify everything with $!, it'd be better for you to use a process more like: . open file . process file . use results from processing the file. . close file probably by moving the withFile outside of getPackageList, to wrap a function that prints the results after they've been obtained. The function passed to withFile should generally include all the processing related to the file and its results, I believe. I tried changing line (1) to return $ map (drop 10) $ filter (startsWith Filename:) $! lines c The $! forces strictness, but since it's deep in the result, it isn't evaluated until it's too late. Chaning it to return $! map (drop 10) $ filter (startsWith Filename:) $ lines c makes getPackageList function return several (but not all) filenames. I think we'd need to see the actual input and expected output, to understand what's going wrong here. It worked fine for me, for small tests. By the way, it's good policy to always post complete, runnable examples. Requiring anyone who wants to help you to write additional code just to get it to run decreases the chances that someone will bother to do so. (Disclaimer: I'm quite new to Haskell myself, so take what I say with more than a pinch of salt.) - -- Micah J. Cowan Programmer, musician, typesetting enthusiast, gamer. GNU Maintainer: wget, screen, teseq http://micah.cowan.name/ -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFI1/AT7M8hyUobTrERAo5qAJ9PKLbQv09UGffmxy6/eRuGS1eYbQCgj3gH 8zvxMrGk5pvCMCOQ6LVz0Yo= =GAvg -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] how do i use quickcheck in the IO monad?
If i have functions in the IO monad, is there a way to use quickcheck to test them? I have a bunch of C bindings that unfortunately are not safe. But i would like to be able to use QuickCheck to test them. Thanks, Anatoly ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Climbing up the shootout...
igouy2: --- Simon Brenner [EMAIL PROTECTED] wrote: On Mon, Sep 22, 2008 at 2:07 PM, Bulat Ziganshin [EMAIL PROTECTED] wrote: this overall test is uselles for speed comparison. afair, there are only 2-3 programs whose speed isn't heavily depend on libraries. in DNA test, for example, Tcl (or PHP?) was leader just because it has better regexp library On the regex-dna benchmark, I'll have to agree. It's unfortunate to have a benchmark so dependent on the set of libraries included in the distribution, and e.g. Text.Regex.PCRE kicks Text.Regex.Posix's behind in this benchmark - but we probably can't use it only because one's bundled and the other isn't. Maybe we could roll our own regexp engine for this specific benchmark though (for example, Text.Regex.TDFA is within 10% or something of PCRE and AFAIK pure Haskell - a customized and downsized version of that could probably be made quite competitive). You could always suggest use of Text.Regex.PCRE, provide a program and instructions on how to install Text.Regex.PCRE on Ubuntu. I've now submitted a Text.Regex.PCRE parallelised entry written by Tim Newsham. It is by far the fastest haskell regex entry so far (down to 9s on quad core, from 100+ seconds on single core for the old entry), http://alioth.debian.org/tracker/index.php?func=detailaid=311132group_id=30402atid=411646 It does require the regex-pcre library, which if it isn't in your package system on Ubuntu, you can certainly build, $ wget http://hackage.haskell.org/packages/archive/regex-pcre-builtin/0.94.2.0.7.7/regex-pcre-builtin-0.94.2.0.7.7.t ar.gz $ tar xzf regex-pcre-builtin-0.94.2.0.7.7.tar.gz $ cd regex-pcre-builtin-0.94.2.0.7.7 $ runhaskell Setup.hs configure --prefix=$HOME $ runhaskell Setup.hs build $ sudo runhaskell Setup.hs install I also included these details on the ticket. It uses a simple parMap strategy. Cheers, Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[6]: [Haskell-cafe] Climbing up the shootout...
--- Bulat Ziganshin [EMAIL PROTECTED] wrote: Hello Graham, i don't think that these 3 libs allows to write high-level high-performance code in *most* cases. just for example, try to write wc without using words. To a newbie, that's a cryptic statement. Are you saying that these libs aren't needed to make a high-performance wc, and that the Prelude functions are sufficient? (I note too that there is Data.ByteString.Char8.words, but I assume you are talking about the Prelude function.) i mean that naive haskell code is very slow and 3 or 5 or twelve libs can't solve the problem of ghc generating slow code Is there something particularly fascinating about naive code written in any language? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Climbing up the shootout...
Don Stewart ha scritto: [...] I've now submitted a Text.Regex.PCRE parallelised entry written by Tim Newsham. It is by far the fastest haskell regex entry so far (down to 9s on quad core, from 100+ seconds on single core for the old entry), http://alioth.debian.org/tracker/index.php?func=detailaid=311132group_id=30402atid=411646 It does require the regex-pcre library, which if it isn't in your package system on Ubuntu, you can certainly build, What performance gain do you obtain using regex-pcre-builtin against a native Haskell regex library? [...] Thanks Manlio Perillo ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[8]: [Haskell-cafe] Climbing up the shootout...
Hello Isaac, Monday, September 22, 2008, 11:49:30 PM, you wrote: i mean that naive haskell code is very slow and 3 or 5 or twelve libs can't solve the problem of ghc generating slow code Is there something particularly fascinating about naive code written in any language? yes, in asm number of instructions executed more or less define number of CPU cycles used. C known as portable asm. Haskell was developed with goal to hide implementation details from egg-headed scientists and this obviously should have some drawbacks -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[8]: [Haskell-cafe] Climbing up the shootout...
On Tue, 2008-09-23 at 00:20 +0400, Bulat Ziganshin wrote: Hello Isaac, Monday, September 22, 2008, 11:49:30 PM, you wrote: i mean that naive haskell code is very slow and 3 or 5 or twelve libs can't solve the problem of ghc generating slow code Is there something particularly fascinating about naive code written in any language? yes, in asm number of instructions executed more or less define number of CPU cycles used. On modern processors (RISC design), naive asm is likely to be extraordinarily slow, because memory usage and cache considerations and register scheduling dominate processor cycles. C known as portable asm. Known as != is. And naive C is also extraordinarily slow, especially if written at a high level. It is not the least bit difficult to write memory hogs in C. (I should know; I've done it. And so has every major software house (including open source projects) to release in C, for that matter.) Haskell was developed with goal to hide implementation details from egg-headed scientists and this obviously should have some drawbacks Should != is. Not all shoot-out entries look like C with Haskell syntax (although some do). Naive Haskell can be 100s of times slower than well-tuned C; naive C can be 100s of times slower than well-tuned Haskell (where well-tuned Haskell can just mean using good data structures. It's quite naive indeed to dismiss better data structures and better algorithms (especially where `better algorithms) as `libraries.) jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: having fun with GADT's
data Nat a where Z :: Nat a S :: Nat a - Nat (S a) data Z data S a I thought I was getting this, but this part is confusing. What exactly does declaring data Z do? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[10]: [Haskell-cafe] Climbing up the shootout...
Hello Jonathan, Tuesday, September 23, 2008, 12:30:19 AM, you wrote: yes, in asm number of instructions executed more or less define number of CPU cycles used. well, i more or less know all this stuff. but are you really compare to Haskell??? does Haskell programs typically written in account of cache misses and CPU ticks? i suggest you to look into two papers i mentioned - they state hundreds times slower naive Haskell vs naive C. it's a reality, against all your arguments -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
Stephan Friedrichs wrote: Andrew Coppin wrote: [...] - Variable names such as x and f aren't fabulously helpful to lost programmers trying to find their way. I'm not a fan of cryptic variable names, either, and I try to use descriptive names wherever I can. But in Haskell... - ... you often have variables, which have a scope of far less than a line such as in map (\(x, (_, y)) - (x, y) ... (cleaning intermediate results from a list). - ... things often get very abstract, so that it just feels wrong matching on, say, (socket:sockets) instead of (x:xs). ...so, more or less the reason why mathematical formulas usually end up with non-descriptive variable names then. ;-) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
Ketil Malde wrote: The rationale for having long names is that you have too many names, and too large a scope to keep track of them all in your head. Needing long names is a symptom that your code is too complex, and that you should refactor it. Well, yeah. In Haskell, functions tend to be rather shorter than in procedural languages, so there's less call for dissambiguation because there are fewer variables in scope. The other problem with descriptive names is that it is not automatically checked by the compiler, and thus it often ends up being misleading. Incorrect documentation is worse than no documentation. That's true enough. Nobody is going to realise that [x] means a list. And C is utterly incomprehensible, since from my Pascal background, I just *know* that curly braces denote comments. Come on, expecting somebody to understand a language without an extremely basic understanding of fundamental syntactical constructs is futile. Point taken. I still think List x would have been clearer, but nobody is going to change the Haskell Report now... well you can see why people are getting lost! ;-) Yes, by refusing to adapt to any syntax but the single one they know. Some people will glance at Haskell and think hey, that doesn't look like source code, I can't read that. But given the number of times I've explained all this stuff, you'd think one or two people would have got it by now... Only if you can figure out that Map means what every other programming language on the face of the Earth calls a dictionary. (This took me a while!) Except for where it is called an associative array or hash table? Terminology is inconsistent, Haskell happens to draw more of it from math than from other programming languages. Heh, let's not argue over technical terms... ;-) Most people seem far more confused by what a fold might be. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: having fun with GADT's
Someone could probably give a better explanation but I'll give this a shot! :) What you are actually doing is defining a family of types. Every value in the type Nat a has it's own type. For instance Z has type Nat Z, (S Z) or one has type Nat (S Z), (S (S Z)) has type Nat (S (S Z)) and so on. In effect types Z and (S a) defined in those data declarations are marker types. It might help you understand if you change the names of the types in the data declarations to something else. It helps not to get confused between types and constructors ;) . I hope this was helpful, Frank On 22 Sep 2008, at 21:42, Anatoly Yakovenko wrote: data Nat a where Z :: Nat a S :: Nat a - Nat (S a) data Z data S a I thought I was getting this, but this part is confusing. What exactly does declaring data Z do? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[10]: [Haskell-cafe] Climbing up the shootout...
On Tue, 2008-09-23 at 00:46 +0400, Bulat Ziganshin wrote: Hello Jonathan, Tuesday, September 23, 2008, 12:30:19 AM, you wrote: yes, in asm number of instructions executed more or less define number of CPU cycles used. well, i more or less know all this stuff. but are you really compare to Haskell??? You were tasked with finding a language where `naive' code is fast. Assembler doesn't count; you have to think about does Haskell programs typically written in account of cache misses and CPU ticks? No. At that level, you write assembler (or C). But assembler and C are usually not written in a naive fashion (not as naive as naive Haskell). And when they do, they suck, performance-wise. i suggest you to look into two papers i mentioned I don't remember the exact citation, but I'm sure I've read them. Probably several times over. Most papers I've seen I think the authors looked for a large contrast; they aren't comparing Haskell and C on truly level ground. - they state hundreds times slower naive Haskell With slow datastructures vs naive C. Not so naive; just better datastructures. Which are then replicated in the relevant papers. And the result is neither extremely low-level code nor 100s of times slower than C. The term `naive' gets thrown around in the introduction to these papers for effect, but the Haskell code under discussion by the time you reach the conclusion isn't much less `naive' than the C code in the introduction. it's a reality, against all your arguments Bang harder!! I don't think the next list over can hear you yet! jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] how do i use quickcheck in the IO monad?
aeyakovenko: If i have functions in the IO monad, is there a way to use quickcheck to test them? I have a bunch of C bindings that unfortunately are not safe. But i would like to be able to use QuickCheck to test them. Typically, via unsafePerformIO, and check the invariants that need to hold for that to be safe by hand. E.g. prop_foo x = unsafePerformIO $ do writeFile f x y - readFile f return (x == y) -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: having fun with GADT's
On Mon, Sep 22, 2008 at 2:42 PM, Anatoly Yakovenko [EMAIL PROTECTED] wrote: data Nat a where Z :: Nat a S :: Nat a - Nat (S a) data Z data S a I thought I was getting this, but this part is confusing. What exactly does declaring data Z do? Well, in Haskell without closed type families, it's not doing all that much. You could use Int or IO Elephant if you wanted to, as long as its head is not S. But it's documentation, because we're really declaring the dependent type (in pseudohaskell): data Nat = Z | S Nat data Bounded :: Nat - * where BZ :: Bounded n BS :: Bounded n - Bounded (S n) So Z and S are the data constructors for Nat, and Bounded *should* only be able to take Nats as arguments. But we cannot express that in Haskell, we just have to be disciplined and never give anything else to Bounded. Luke ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Most people seem far more confused by what a fold might be. A fold by any other name would smell as sweet. ;) -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.8 (Darwin) iEYEARECAAYFAkjYE7kACgkQTkPEVFd3yxh7HwCfVzopoOCgg49YI0Y88g9rjXqI DvcAn3Buv4FmqcYrK5pDLr1iUc7XRpO5 =CKiH -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[6]: [Haskell-cafe] Climbing up the shootout...
Hello Bulat, On Mon, Sep 22, 2008 at 3:09 PM, Bulat Ziganshin [EMAIL PROTECTED]wrote: Hello Graham, i don't think that these 3 libs allows to write high-level high-performance code in *most* cases. just for example, try to write wc without using words. To a newbie, that's a cryptic statement. Are you saying that these libs aren't needed to make a high-performance wc, and that the Prelude functions are sufficient? (I note too that there is Data.ByteString.Char8.words, but I assume you are talking about the Prelude function.) i mean that naive haskell code is very slow and 3 or 5 or twelve libs can't solve the problem of ghc generating slow code I'm fairly new to Haskell and the Haskell community, but I can say from my experience of hacking on GHC, the GHC team of developers are very interested in performance improvements, e.g. this thread is about performance! So Bulat, why don't you hack on GHC yourself and help improve the compiler? Or suggest detailed improvements since you seem capable of citing specific examples? Thank you. __ Donnie ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[8]: [Haskell-cafe] Climbing up the shootout...
Hello Donnie, Tuesday, September 23, 2008, 2:53:17 AM, you wrote: i mean that naive haskell code is very slow and 3 or 5 or twelve libs can't solve the problem of ghc generating slow code I'm fairly new to Haskell and the Haskell community, but I can say from my experience of hacking on GHC, the GHC team of developers are very interested in performance improvements, e.g. this thread is about performance! So Bulat, why don't you hack on GHC yourself and help improve the compiler? Or suggest detailed improvements since you seem capable of citing specific examples? for the same reason i don't feed 5000 men with 7 breads - it's not my business ;) -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Live twittering from ICFP
ICFP is on now, for those wondering why the list is a bit quiet :) http://www.icfpconference.org/icfp2008/schedule.html I'm doing live updates of events at ICFP/Haskell Symposium here in Canada. http://twitter.com/galoisinc So you can follow events remotely. Cheers, Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Climbing up the shootout...
bulat.ziganshin: Hello Donnie, Tuesday, September 23, 2008, 2:53:17 AM, you wrote: i mean that naive haskell code is very slow and 3 or 5 or twelve libs can't solve the problem of ghc generating slow code I'm fairly new to Haskell and the Haskell community, but I can say from my experience of hacking on GHC, the GHC team of developers are very interested in performance improvements, e.g. this thread is about performance! So Bulat, why don't you hack on GHC yourself and help improve the compiler? Or suggest detailed improvements since you seem capable of citing specific examples? for the same reason i don't feed 5000 men with 7 breads - it's not my business ;) Ok. So I'll just say: high level, efficient code is an overriding theme of many individuals working on Haskell. Things are better and better each year. We do not stand still. For example, Bulat cites a paper talking about naive list code from 2002, however, by 2008 we know how to do fusion on lists, so it runs in the same time as low level loops, the technique is implemented and you can download it from hackage, http://hackage.haskell.org/cgi-bin/hackage-scripts/package/stream-fusion Simon Marlow is busy adding more efficient GC and parallelism to GHC, and there's a summer project to rewrite the native code generator. GHC gained pointer tagging in the last release cycle, dramatically reducing the cost of algebraic data types. At the same time, we're writing books about how to program naively in Haskell, such that your code doesn't suck. That is: training. Teaching people how to write Haskell. We can see it paying off, where naive code performs very very well, http://shootout.alioth.debian.org/gp4/benchmark.php?test=sumcollang=all And lots and lots more people able to write good code for Hackage. I find Bulat's outlook rather bleak, and I think it is time to update expectations. Progress is beautiful. -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Climbing up the shootout...
On 2008.09.22 21:12:06 +0400, Bulat Ziganshin [EMAIL PROTECTED] scribbled 0.5K characters: Hello Simon, Monday, September 22, 2008, 9:03:52 PM, you wrote: With bytestrings, unboxed arrays, light-weight threads and other tricks, we can usually replace all those ugly low-level programs with nice high-level haskell ones i don't think that these 3 libs allows to write high-level high-performance code in *most* cases. just for example, try to write wc without using words -- Best regards, Bulatmailto:[EMAIL PROTECTED] http://haskell.org/haskellwiki/Wc seems to do fine; you'll notice it drops lines after the first version. -- gwern class ASPIC Duress BNC WWSV of intelligence retrieval Al PRF signature.asc Description: Digital signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Climbing up the shootout...
Hello Gwern, Tuesday, September 23, 2008, 3:33:02 AM, you wrote: high-performance code in *most* cases. just for example, try to write wc without using words http://haskell.org/haskellwiki/Wc seems to do fine; you'll notice it drops lines after the first version. actually it counts lines using built-in function. you may find that naive C is 6x fatser than naive Haskell and difference is so small only because C version is bound by memory speed -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Climbing up the shootout...
2008/9/23 Bulat Ziganshin [EMAIL PROTECTED]: http://haskell.org/haskellwiki/Wc seems to do fine; you'll notice it drops lines after the first version. actually it counts lines using built-in function. you may find that naive C is 6x fatser than naive Haskell and difference is so small only because C version is bound by memory speed So what ? Strings represented as lists of character are slow ? What an incredible discovery ! The ByteString versions are fast, ByteString was invented especially for IO intensive situation, it's a library you can use pretty naively and mostly get excellent performances, what exactly isn't Haskelly enough for you in this solution ? The guts of ByteString aren't idiomatic Haskell ? And ? The guts of the JVM aren't written in Java either... At least ByteString was built over GHC which means it can be done. Besides a part of the performances of ByteString comes from stream fusion and that's specifically something that is hard to achieve outside of Haskell... What exactly is your point ? - Haskell is slow, we can't make it faster ? That's obviously false as demonstrated by the progress in the latest years. - Haskell is slower than C ? Well that's probably true, because C can touch the hardware directly and can always optimize every single aspects of a computation... On the other hand that kind of uber optimization has a cost that I am unwilling to pay, I would rather write high level Haskell and pay a little hit on execution time. - We shouldn't center ourselves around performance to promote Haskell (or should we even promote Haskell) ? Well there you may have a point, but maybe it would be better to just make it and avoid denying other peoples efforts to make Haskell faster ? -- Jedaï ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Climbing up the shootout...
bulat.ziganshin: when gcc developers will start to add to C libraries functions performing shootout benchmarks we will continue this discussion :D atoi(3). -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Climbing up the shootout...
Hello Don, Tuesday, September 23, 2008, 4:22:19 AM, you wrote: bulat.ziganshin: when gcc developers will start to add to C libraries functions performing shootout benchmarks we will continue this discussion :D atoi(3). it isn't the same as readInt which was added specifically for this test. it doesn't support arbitrary-size streams and doesn't return rest of stream -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Climbing up the shootout...
bulat.ziganshin: Hello Don, Tuesday, September 23, 2008, 4:22:19 AM, you wrote: bulat.ziganshin: when gcc developers will start to add to C libraries functions performing shootout benchmarks we will continue this discussion :D atoi(3). it isn't the same as readInt which was added specifically for this test. it doesn't support arbitrary-size streams and doesn't return rest of stream Hmm? That is wrong. These functions explicitly work on arbitrarily long lazy bytestrings, and return the rest of the stream in a pair: readInt :: ByteString - Maybe (Int, ByteString) readInteger :: ByteString - Maybe (Integer, ByteString) These are the initial parts of a bytestring lexing library, more of which is appareing in the bytestring-lex package on Hackage. -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Climbing up the shootout...
2008/9/23 Bulat Ziganshin [EMAIL PROTECTED]: Hello Don, Tuesday, September 23, 2008, 4:22:19 AM, you wrote: bulat.ziganshin: when gcc developers will start to add to C libraries functions performing shootout benchmarks we will continue this discussion :D atoi(3). it isn't the same as readInt which was added specifically for this test. it doesn't support arbitrary-size streams and doesn't return rest of stream Yeah, readInt has a more useful type than atoi() in most circumstances so obviously it's a default which somehow disqualify this function... (I wasn't aware that this function was only useful in the shoutout context, I should probably scrap it from my other programs now) I think we should write all the entries in Haskell98 and disable any optimisation in GHC too, that would gives us a much fairer vision of Haskell current performances. -- Jedaï ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line noise
On Sun, 21 Sep 2008, wren ng thornton wrote: Even with functionalists ---of the OCaml and SML ilk--- this use of spaces can be confusing if noone explains that function application binds tighter than all operators. Bwuh? Ocaml programmers certainly know that application binds tighter than operators. And as: let f x y = ... in f a b is more efficient (in Ocaml) than: let f (x, y) = ... in f (a, b) (Ocaml doesn't optimize away the tuple allocation), the former (Haskell-like) is generally preferred by Ocaml programmers. SML programmers do use the second form, I'll grant you. Brian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Climbing up the shootout...
Hello Don, Tuesday, September 23, 2008, 4:36:55 AM, you wrote: it isn't the same as readInt which was added specifically for this test. it doesn't support arbitrary-size streams and doesn't return rest of stream Hmm? That is wrong. These functions explicitly work on arbitrarily long lazy bytestrings, and return the rest of the stream in a pair: lazy bytestring which is read from file on demand is the same as arbitrary-sized stream. equivalent C code would be much faster (and probably limited by memory speed) readInt :: ByteString - Maybe (Int, ByteString) readInteger :: ByteString - Maybe (Integer, ByteString) These are the initial parts of a bytestring lexing library, more of which is appareing in the bytestring-lex package on Hackage. readInt was added to FPS library by you and immediately used to improve speed of this benchmark two years ago. there was no readInteger since shootout doesn't contain such benchmarks :) -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[4]: [Haskell-cafe] Climbing up the shootout...
Hello Chaddaï, Tuesday, September 23, 2008, 4:39:18 AM, you wrote: it isn't the same as readInt which was added specifically for this test. it doesn't support arbitrary-size streams and doesn't return rest of stream I think we should write all the entries in Haskell98 and disable any optimisation in GHC too, that would gives us a much fairer vision of Haskell current performances. well, it's what C developers does. just look at full list of C and Haskell entries for this benchmark - all qualified C programs used std C/C++ libs, several really optimized entries was disqualified. and then Don found genious solution to the problem - add this function to GHC libs. or shootout wasn't first usage of this function? -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: [Haskell-cafe] Climbing up the shootout...
At the risk of getting sucked into a silly discussion, I'd like to point out that the c code uses the following really simple and naive function: http://sourceware.org/cgi-bin/cvsweb.cgi/libc/stdlib/strtol.c?rev=1.42.2.2content-type=text/x-cvsweb-markupcvsroot=glibc http://sourceware.org/cgi-bin/cvsweb.cgi/libc/stdlib/strtol_l.c?rev=1.4.2.3content-type=text/x-cvsweb-markupcvsroot=glibc Oh, and it simply and naively loops with the following: while (fgets_unlocked (line, MAXLINELEN, stdin)) If Bulat's point is that the shootout has inspired work on Haskell performance, and in the stdlibs no less, then lovely, and that's all to the good. Below every high level interface is lots of low level pain. If his point is anything else, this is getting absurd. --S On Mon, Sep 22, 2008 at 8:16 PM, Bulat Ziganshin [EMAIL PROTECTED]wrote: Hello Don, Tuesday, September 23, 2008, 3:12:37 AM, you wrote: for the same reason i don't feed 5000 men with 7 breads - it's not my business ;) Ok. So I'll just say: high level, efficient code is an overriding theme of many individuals working on Haskell. Things are better and better each year. We do not stand still. yes. when we say that things are greatly improving each year, this means that they was bad previously ;) For example, Bulat cites a paper talking about naive list code from 2002, however, by 2008 we know how to do fusion on lists, so it runs in the same time as low level loops, the technique is implemented and you can download it from hackage, http://hackage.haskell.org/cgi-bin/hackage-scripts/package/stream-fusion someone can ask why this great code isn't used in ghc by default. probably it is just work in progress which isn't yet ready to replace old slow code. then we can see tha fusion isn't magic wand which improves speed of every haskell code that's slower than C one. it just makes C-speed code sometimes Simon Marlow is busy adding more efficient GC and parallelism to GHC, and there's a summer project to rewrite the native code generator. well, i'm sais about *current* real situation. if you consider this as attack against Haskell developers, it's your mistake. the problem is that i many years wrote about slowness of ghc code, every time you cosider this as attack and write that in future Haskell will become much faster. we still wait for this future, however GHC gained pointer tagging in the last release cycle, dramatically reducing the cost of algebraic data types. 10-20% speed improvement, on average. it's the only real improvement (for my own program) i know. i think that ByteString-related libs gived more improvements but their use isn't automatic and they doesn't help in any situation. they just provide fast library code for solving some concrete (although very frequent) situations, such as counting lines At the same time, we're writing books about how to program naively in Haskell, such that your code doesn't suck. That is: training. Teaching people how to write Haskell. it is what i say - if naive code was effective and automagically optimized by ghc, we don't need all those tutorials. anyone looked into your tutorial on writing efficient Haskell code, will never say that it's easier than in C. so we can conclude that optimized haskell programs are several times slower than C ones and need several times more to write We can see it paying off, where naive code performs very very well, http://shootout.alioth.debian.org/gp4/benchmark.php?test=sumcollang=all yes! it's my beloved example of elegant haskell code entirely based on the readInt function added to ghc libs specifically to win in this test. it's implementation is really simple and naive: -- - -- Reading from ByteStrings -- | readInt reads an Int from the beginning of the ByteString. If there is no -- integer at the beginning of the string, it returns Nothing, otherwise -- it just returns the int read, and the rest of the string. readInt :: ByteString - Maybe (Int, ByteString) readInt as | null as = Nothing | otherwise = case unsafeHead as of '-' - loop True 0 0 (unsafeTail as) '+' - loop False 0 0 (unsafeTail as) _ - loop False 0 0 as where loop :: Bool - Int - Int - ByteString - Maybe (Int, ByteString) STRICT4(loop) loop neg i n ps | null ps = end neg i n ps | otherwise = case B.unsafeHead ps of w | w = 0x30 w = 0x39 - loop neg (i+1) (n * 10 + (fromIntegral w - 0x30)) (unsafeTail ps) | otherwise - end neg i n ps end _0 _ _ = Nothing end True _ n ps = Just (negate n, ps) end __ n ps = Just (n, ps) when gcc
Re: [Haskell-cafe] Line noise
On Mon, Sep 22, 2008 at 6:27 PM, Brian Hurt [EMAIL PROTECTED] wrote: On Sun, 21 Sep 2008, wren ng thornton wrote: Even with functionalists ---of the OCaml and SML ilk--- this use of spaces can be confusing if noone explains that function application binds tighter than all operators. Bwuh? Ocaml programmers certainly know that application binds tighter than operators. And as: let f x y = ... in f a b is more efficient (in Ocaml) than: let f (x, y) = ... in f (a, b) (Ocaml doesn't optimize away the tuple allocation), the former (Haskell-like) is generally preferred by Ocaml programmers. That's odd. My experience from trying to learn ocaml at one point was that the tuple notation is preferable because you can do pattern matching on every value in the tuple whereas with the other one you can match on either the first or second parameter but not both without nesting ocaml's version of 'case ... of' (match ... with?). One of the things I really like about Haskell syntax is that you can pattern match on any number of parameters without having to nest 'case ... of' expressions. Jason ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Is there already an abstraction for this?
Hello, I am trying to figure out if there is an existing abstraction I am missing here. I have an expression data-type: data Expr = Quotient Expr Expr | Product Expr Expr | Sum Expr Expr | Difference Expr Expr | Lit Double | Var Char deriving (Eq, Ord, Data, Typeable, Read, Show) And I want to write a function that will take an expression and automatically apply the identity laws to simplify the expression. The basic identity laws are: a + 0 = a a * 1 = a I can implement these with some 'sugar' as: identity (Sum (Lit 0) a)= a identity (Sum a (Lit 0))= a identity (Difference a (Lit 0)) = a identity (Product a (Lit 1))= a identity (Product (Lit 1) a)= a identity (Quotient a (Lit 1)) = a identity a = a This works fine when the identity only needs to be applied to the root of the expression tree: *Main ppExpr $ identity (expr 1 + 0) 1 But for more complicated trees it does not fully apply the identity laws: *Main ppExpr $ identity (expr 0 + (0 + 0) + (0 + 0)) ((0 + 0) + (0 + 0)) What we need to do is first apply the identity function to the children, and then apply them to the parent of the updated children. A first attempt would be to extend the identity function like this: identity (Sum a b) = identity (Sum (identity a) (identity b)) However, that will not terminate because that same case will keep matching over and over. Another approach is to have two mutually recursive functions like: identity' (Sum (Lit 0) a)= identityRec a identity' (Sum a (Lit 0))= identityRec a identity' a = a identityRec (Sum a b) = identity' (Sum (identity' a) (identity' b)) This prevents non-termination, but you have to be careful about calling identity' vs identityRec or you will either re-introduce non-termination, or you may not fully apply the identity laws. Another option to create a helper function like: -- |Deep map of an expression. eMap :: (Expr - Expr) - Expr - Expr eMap f (Sum a b) = f (Sum (eMap f a) (eMap f b)) eMap f (Difference a b) = f (Difference (eMap f a) (eMap f b)) eMap f (Product a b) = f (Product (eMap f a) (eMap f b)) eMap f (Quotient a b) = f (Quotient (eMap f a) (eMap f b)) eMap f (Var v) = f (Var v) eMap f (Lit i) = f (Lit i) Now we can easily apply the identity law recursively like: deepIdentity :: Expr - Expr deepIdentity = eMap identity *Main ppExpr (deepIdentity (expr 0 + (0 + 0) + (0 + 0))) 0 Sweet! But, having to write eMap out by hand like that somehow feels wrong -- as if I am missing some additional abstraction. In some respects eMap is like a Functor, but not quite. I expect there is a way to implement eMap using Data.Generics, which is perhaps better, but I still feel like that is missing something? Anyway, I just thought I would ask in case someone recognized this pattern and could point me in the right direction. I have attached a working example program you can play with. I would also be interested in alternative approaches besides the ones I outlined. thanks! j. {-# LANGUAGE DeriveDataTypeable #-} import Control.Applicative (Applicative((*), pure), (*), (*)) import Control.Monad (ap) import Data.Generics (Typeable, Data) import Data.List (isSuffixOf) import Text.ParserCombinators.Parsec ((|)) import qualified Text.ParserCombinators.Parsec as P import qualified Text.ParserCombinators.Parsec.Expr as P import Text.PrettyPrint.HughesPJ ((+)) import qualified Text.PrettyPrint.HughesPJ as H import Prelude hiding (sum, product) data Expr = Quotient Expr Expr | Product Expr Expr | Sum Expr Expr | Difference Expr Expr | Lit Double | Var Char deriving (Eq, Ord, Data, Typeable, Read, Show) instance Applicative (P.GenParser token state) where pure = return (*) = ap parseExpr :: P.GenParser Char st Expr parseExpr = P.buildExpressionParser optable (lit | var | parenExpr) where parenExpr = (P.char '(' P.skipMany P.space) * parseExpr * (P.char ')' P.skipMany P.space) optable = [ [ P.Infix (P.char '/' P.skipMany P.space return Quotient) P.AssocLeft ] , [ P.Infix (P.char '*' P.skipMany P.space return Product) P.AssocRight ] , [ P.Infix (P.char '+' P.skipMany P.space return Sum) P.AssocRight ] , [ P.Infix (P.char '-' P.skipMany P.space return Difference) P.AssocLeft ] ] lit = do d - P.try (P.many1 $ P.oneOf ('-' : '.' : ['0'..'9'])) P.skipMany P.space return (Lit (read d)) var = do sign - (P.char '-' return (\x - (Product (Lit (-1)) x))) | (return id) v - (P.upper | P.lower) P.skipMany P.space return (sign (Var v)) expr :: String - Expr expr str = either (error .show) id (P.parse parseExpr str str) ppExpr :: Expr - H.Doc ppExpr (Lit i)
Re: [Haskell-cafe] Is there already an abstraction for this?
I can implement these with some 'sugar' as: identity (Sum (Lit 0) a)= a identity (Sum a (Lit 0))= a identity (Difference a (Lit 0)) = a identity (Product a (Lit 1))= a identity (Product (Lit 1) a)= a identity (Quotient a (Lit 1)) = a identity a = a Why do you need mutual recursion? What's wrong with: identity (Sum (Lit 0) a)= identity a ... identity (Quotient a (Lit 1)) = identity a identity a = a Structural recursion ensures that this always terminates. Dan Jeremy Shaw wrote: Hello, I am trying to figure out if there is an existing abstraction I am missing here. I have an expression data-type: data Expr = Quotient Expr Expr | Product Expr Expr | Sum Expr Expr | Difference Expr Expr | Lit Double | Var Char deriving (Eq, Ord, Data, Typeable, Read, Show) And I want to write a function that will take an expression and automatically apply the identity laws to simplify the expression. The basic identity laws are: a + 0 = a a * 1 = a I can implement these with some 'sugar' as: identity (Sum (Lit 0) a)= a identity (Sum a (Lit 0))= a identity (Difference a (Lit 0)) = a identity (Product a (Lit 1))= a identity (Product (Lit 1) a)= a identity (Quotient a (Lit 1)) = a identity a = a This works fine when the identity only needs to be applied to the root of the expression tree: *Main ppExpr $ identity (expr 1 + 0) 1 But for more complicated trees it does not fully apply the identity laws: *Main ppExpr $ identity (expr 0 + (0 + 0) + (0 + 0)) ((0 + 0) + (0 + 0)) What we need to do is first apply the identity function to the children, and then apply them to the parent of the updated children. A first attempt would be to extend the identity function like this: identity (Sum a b) = identity (Sum (identity a) (identity b)) However, that will not terminate because that same case will keep matching over and over. Another approach is to have two mutually recursive functions like: identity' (Sum (Lit 0) a)= identityRec a identity' (Sum a (Lit 0))= identityRec a identity' a = a identityRec (Sum a b) = identity' (Sum (identity' a) (identity' b)) This prevents non-termination, but you have to be careful about calling identity' vs identityRec or you will either re-introduce non-termination, or you may not fully apply the identity laws. Another option to create a helper function like: -- |Deep map of an expression. eMap :: (Expr - Expr) - Expr - Expr eMap f (Sum a b) = f (Sum (eMap f a) (eMap f b)) eMap f (Difference a b) = f (Difference (eMap f a) (eMap f b)) eMap f (Product a b) = f (Product (eMap f a) (eMap f b)) eMap f (Quotient a b) = f (Quotient (eMap f a) (eMap f b)) eMap f (Var v) = f (Var v) eMap f (Lit i) = f (Lit i) Now we can easily apply the identity law recursively like: deepIdentity :: Expr - Expr deepIdentity = eMap identity *Main ppExpr (deepIdentity (expr 0 + (0 + 0) + (0 + 0))) 0 Sweet! But, having to write eMap out by hand like that somehow feels wrong -- as if I am missing some additional abstraction. In some respects eMap is like a Functor, but not quite. I expect there is a way to implement eMap using Data.Generics, which is perhaps better, but I still feel like that is missing something? Anyway, I just thought I would ask in case someone recognized this pattern and could point me in the right direction. I have attached a working example program you can play with. I would also be interested in alternative approaches besides the ones I outlined. thanks! j. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is there already an abstraction for this?
Oops, never mind. This is just the shallow application you referred to. Too fast with that send button! Dan Weston wrote: I can implement these with some 'sugar' as: identity (Sum (Lit 0) a)= a identity (Sum a (Lit 0))= a identity (Difference a (Lit 0)) = a identity (Product a (Lit 1))= a identity (Product (Lit 1) a)= a identity (Quotient a (Lit 1)) = a identity a = a Why do you need mutual recursion? What's wrong with: identity (Sum (Lit 0) a)= identity a ... identity (Quotient a (Lit 1)) = identity a identity a = a Structural recursion ensures that this always terminates. Dan Jeremy Shaw wrote: Hello, I am trying to figure out if there is an existing abstraction I am missing here. I have an expression data-type: data Expr= Quotient Expr Expr | Product Expr Expr | Sum Expr Expr | Difference Expr Expr | Lit Double | Var Char deriving (Eq, Ord, Data, Typeable, Read, Show) And I want to write a function that will take an expression and automatically apply the identity laws to simplify the expression. The basic identity laws are: a + 0 = a a * 1 = a I can implement these with some 'sugar' as: identity (Sum (Lit 0) a)= a identity (Sum a (Lit 0))= a identity (Difference a (Lit 0)) = a identity (Product a (Lit 1))= a identity (Product (Lit 1) a)= a identity (Quotient a (Lit 1)) = a identity a = a This works fine when the identity only needs to be applied to the root of the expression tree: *Main ppExpr $ identity (expr 1 + 0) 1 But for more complicated trees it does not fully apply the identity laws: *Main ppExpr $ identity (expr 0 + (0 + 0) + (0 + 0)) ((0 + 0) + (0 + 0)) What we need to do is first apply the identity function to the children, and then apply them to the parent of the updated children. A first attempt would be to extend the identity function like this: identity (Sum a b) = identity (Sum (identity a) (identity b)) However, that will not terminate because that same case will keep matching over and over. Another approach is to have two mutually recursive functions like: identity' (Sum (Lit 0) a)= identityRec a identity' (Sum a (Lit 0))= identityRec a identity' a = a identityRec (Sum a b) = identity' (Sum (identity' a) (identity' b)) This prevents non-termination, but you have to be careful about calling identity' vs identityRec or you will either re-introduce non-termination, or you may not fully apply the identity laws. Another option to create a helper function like: -- |Deep map of an expression. eMap :: (Expr - Expr) - Expr - Expr eMap f (Sum a b) = f (Sum (eMap f a) (eMap f b)) eMap f (Difference a b) = f (Difference (eMap f a) (eMap f b)) eMap f (Product a b) = f (Product (eMap f a) (eMap f b)) eMap f (Quotient a b) = f (Quotient (eMap f a) (eMap f b)) eMap f (Var v) = f (Var v) eMap f (Lit i) = f (Lit i) Now we can easily apply the identity law recursively like: deepIdentity :: Expr - Expr deepIdentity = eMap identity *Main ppExpr (deepIdentity (expr 0 + (0 + 0) + (0 + 0))) 0 Sweet! But, having to write eMap out by hand like that somehow feels wrong -- as if I am missing some additional abstraction. In some respects eMap is like a Functor, but not quite. I expect there is a way to implement eMap using Data.Generics, which is perhaps better, but I still feel like that is missing something? Anyway, I just thought I would ask in case someone recognized this pattern and could point me in the right direction. I have attached a working example program you can play with. I would also be interested in alternative approaches besides the ones I outlined. thanks! j. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: having fun with GADT's
data Nat a where Z :: Nat a S :: Nat a - Nat (S a) data Z data S a n00 = Z n01 = S n00 n02 = S n01 n03 = S n02 n04 = S n03 data MaxList t where Nil :: MaxList a Cons :: Nat a - MaxList a - MaxList a a = Cons n02 $ Cons n02 $ Cons n01 $ Nil --- :t a gives forall a. MaxList (S (S a)) which tells you exactly --- what you want: elements are at least 2. mlTail :: forall t. MaxList t - MaxList t mlTail (Cons h t) = t Is there a way to define a function that only takes a list with a max of 1? Because only1 :: MaxList (S a) - String only1 _ = only1 will work over a = Cons n02 $ Cons n02 $ Cons n01 $ Nil without any problems ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is there already an abstraction for this?
Hi Jeremy, There are some approaches that support such generic transformations. The simplest is probably Uniplate by Neil Mitchell: http://www-users.cs.york.ac.uk/~ndm/uniplate/ The function 'rewrite' is what you are looking for. If you change the definition of 'identity' to: identity (Sum (Lit 0) a)= Just a identity (Sum a (Lit 0))= Just a identity (Difference a (Lit 0)) = Just a identity (Product a (Lit 1))= Just a identity (Product (Lit 1) a)= Just a identity (Quotient a (Lit 1)) = Just a identity _ = Nothing then the function 'rewrite identity :: Expr - Expr' does what you want. Cheers, Sebastian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: having fun with GADT's
On Mon, Sep 22, 2008 at 10:20 PM, Anatoly Yakovenko [EMAIL PROTECTED] wrote: Is there a way to define a function that only takes a list with a max of 1? Because only1 :: MaxList (S a) - String only1 _ = only1 will work over a = Cons n02 $ Cons n02 $ Cons n01 $ Nil without any problems only1 :: MaxList (S Z) - String If you like, you may declare type One = S Z type Two = S One etc. -- Dave Menendez [EMAIL PROTECTED] http://www.eyrie.org/~zednenem/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: having fun with GADT's
type One = S Z type Two = S One etc. why does: data Nat a where Z :: Nat a S :: Nat a - Nat (S a) data Z data S a type One = S Z n00 = Z n01::One = S n00 give me: test.hs:10:11: Couldn't match expected type `One' against inferred type `Nat (S a)' In the expression: S n00 In a pattern binding: n01 :: One = S n00 Failed, modules loaded: none. or better yet, how is type S Z different from, n01 :: forall a. Nat (S a) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Bird-style and blank lines
Oops, meant to send this to the whole list. You can add -optL -q to your ghc command line to disable that behavior; blank lines will no longer be required. -- ryan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: having fun with GADT's
Try n01 :: Nat One -- ryan On Mon, Sep 22, 2008 at 8:10 PM, Anatoly Yakovenko [EMAIL PROTECTED] wrote: type One = S Z type Two = S One etc. why does: data Nat a where Z :: Nat a S :: Nat a - Nat (S a) data Z data S a type One = S Z n00 = Z n01::One = S n00 give me: test.hs:10:11: Couldn't match expected type `One' against inferred type `Nat (S a)' In the expression: S n00 In a pattern binding: n01 :: One = S n00 Failed, modules loaded: none. or better yet, how is type S Z different from, n01 :: forall a. Nat (S a) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Bird-style and blank lines
On Mon, Sep 22, 2008 at 11:27 PM, Ryan Ingram [EMAIL PROTECTED] wrote: Oops, meant to send this to the whole list. You can add -optL -q to your ghc command line to disable that behavior; blank lines will no longer be required. This little gem that Ryan found was exactly what I was looking for, thank you again, Ryan. So this is already possible in GHC, which is what I use. The question now is whether this is relevant enough to be brought to the attention of people discussing Haskell Prime. If you think it is, let me know, I'll see what I have to do about it. I'll update the Wiki with this information. Thanks everybody, Paulo ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Updated formlets sample?
Ah yes, I just adjusted the code until it compiled, I must confess I didn't check whether it actually worked ;). Thanks for the wiki-update! -chris On 22 sep 2008, at 09:47, Martin Huschenbett wrote: Hi Chris, you're absolutely right. The mistake was in the where-part of withForm. The function handleOk' gets an environment d as argument but uses an extractor that was created without passing d to runFormState. I've put a corrected version on hpaste [1] and also posted it to the wiki on haskell.org [2]. Hope this is ok for you? Regards, Martin. [1] http://hpaste.org/10568#a1 [2] http://haskell.org/haskellwiki/Formlets Chris Eidhof schrieb: That means that you don't have input0 in your environment, maybe you're passing in an empty environment? -chris On 21 sep 2008, at 12:11, Martin Huschenbett wrote: Hi Chris, thanks for the updated example. Compiling works now. But when I try to run it I alway get error messages like [input0 is not in the data,input1 is not in the data] Regards, Martin. Chris Eidhof schrieb: Hey Martin, On 19 sep 2008, at 04:14, Martin Huschenbett wrote: I found a blog post concerning formlets [1] in the web. Since looks very interesting I tried to compile the sample code with recent versions of HAppS and formlets from hackage. But this didn't work as the API of formlets has changed since this post. I tried to adopt the code to the new API but I was unable to finish this since there is a new monadic context I don't know to handle in the right way. So my question is, is there an updated version of this sample code in the web or has anybody tried to adopt it and can send me the results? Yes, I'm sorry for that. The API is still very immature and due to changes, that's also why it hasn't been officially announced yet. I've just put an updated example at http://hpaste.org/10568, hope that'll work for you. I guess we should build a small homepage / wikipage that always has an up-to-date example. -chris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is there already an abstraction for this?
Excerpts from Jeremy Shaw's message of Mon Sep 22 18:46:22 -0700 2008: Hello, I am trying to figure out if there is an existing abstraction I am missing here. You can try to pick some information in the mocac [1] project, that is for OCaml. Moca is a general construction functions generator for Caml data types with invariants. Moca supports two kinds of relations: * algebraic relations (such as associativity or commutativity of a binary constructor), * general rewrite rules that map some pattern of constructors and variables to some arbitrary user's define expression. [1]: http://moca.inria.fr/eng.htm Best regards, I have an expression data-type: data Expr = Quotient Expr Expr | Product Expr Expr | Sum Expr Expr | Difference Expr Expr | Lit Double | Var Char deriving (Eq, Ord, Data, Typeable, Read, Show) And I want to write a function that will take an expression and automatically apply the identity laws to simplify the expression. The basic identity laws are: a + 0 = a a * 1 = a I can implement these with some 'sugar' as: identity (Sum (Lit 0) a)= a identity (Sum a (Lit 0))= a identity (Difference a (Lit 0)) = a identity (Product a (Lit 1))= a identity (Product (Lit 1) a)= a identity (Quotient a (Lit 1)) = a identity a = a This works fine when the identity only needs to be applied to the root of the expression tree: *Main ppExpr $ identity (expr 1 + 0) 1 But for more complicated trees it does not fully apply the identity laws: *Main ppExpr $ identity (expr 0 + (0 + 0) + (0 + 0)) ((0 + 0) + (0 + 0)) What we need to do is first apply the identity function to the children, and then apply them to the parent of the updated children. A first attempt would be to extend the identity function like this: identity (Sum a b) = identity (Sum (identity a) (identity b)) However, that will not terminate because that same case will keep matching over and over. Another approach is to have two mutually recursive functions like: identity' (Sum (Lit 0) a)= identityRec a identity' (Sum a (Lit 0))= identityRec a identity' a = a identityRec (Sum a b) = identity' (Sum (identity' a) (identity' b)) This prevents non-termination, but you have to be careful about calling identity' vs identityRec or you will either re-introduce non-termination, or you may not fully apply the identity laws. Another option to create a helper function like: -- |Deep map of an expression. eMap :: (Expr - Expr) - Expr - Expr eMap f (Sum a b) = f (Sum (eMap f a) (eMap f b)) eMap f (Difference a b) = f (Difference (eMap f a) (eMap f b)) eMap f (Product a b) = f (Product (eMap f a) (eMap f b)) eMap f (Quotient a b) = f (Quotient (eMap f a) (eMap f b)) eMap f (Var v) = f (Var v) eMap f (Lit i) = f (Lit i) Now we can easily apply the identity law recursively like: deepIdentity :: Expr - Expr deepIdentity = eMap identity *Main ppExpr (deepIdentity (expr 0 + (0 + 0) + (0 + 0))) 0 Sweet! But, having to write eMap out by hand like that somehow feels wrong -- as if I am missing some additional abstraction. In some respects eMap is like a Functor, but not quite. I expect there is a way to implement eMap using Data.Generics, which is perhaps better, but I still feel like that is missing something? Anyway, I just thought I would ask in case someone recognized this pattern and could point me in the right direction. I have attached a working example program you can play with. I would also be interested in alternative approaches besides the ones I outlined. thanks! j. {-# LANGUAGE DeriveDataTypeable #-} import Control.Applicative (Applicative((*), pure), (*), (*)) import Control.Monad (ap) import Data.Generics (Typeable, Data) import Data.List (isSuffixOf) import Text.ParserCombinators.Parsec ((|)) import qualified Text.ParserCombinators.Parsec as P import qualified Text.ParserCombinators.Parsec.Expr as P import Text.PrettyPrint.HughesPJ ((+)) import qualified Text.PrettyPrint.HughesPJ as H import Prelude hiding (sum, product) data Expr = Quotient Expr Expr | Product Expr Expr | Sum Expr Expr | Difference Expr Expr | Lit Double | Var Char deriving (Eq, Ord, Data, Typeable, Read, Show) instance Applicative (P.GenParser token state) where pure = return (*) = ap parseExpr :: P.GenParser Char st Expr parseExpr = P.buildExpressionParser optable (lit | var | parenExpr) where parenExpr = (P.char '(' P.skipMany P.space) * parseExpr * (P.char ')' P.skipMany P.space) optable = [ [ P.Infix (P.char '/' P.skipMany P.space return Quotient) P.AssocLeft ] , [ P.Infix (P.char '*' P.skipMany P.space return Product)
[Haskell-cafe] what is the magic hash?
It is not much covered in the docs. It has something to do with magic triggered by a postfix octothorpe? -- _jsn |...docs.| http://haskell.org/ghc/docs/latest/html/users_guide/flag-reference.html ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] what is the magic hash?
On Mon, 2008-09-22 at 21:58 -0700, Jason Dusek wrote: It is not much covered in the docs. It has something to do with magic triggered by a postfix octothorpe? All it does is allow them in identifiers. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] what is the magic hash?
Derek Elkins [EMAIL PROTECTED] wrote: Jason Dusek wrote: It is not much covered in the docs. It has something to do with magic triggered by a postfix octothorpe? All it does is allow them in identifiers. That's it? So it's for use in conjunction with primitive types, I guess (those seem to be denoted like 'Int#')? With the fancy name and the absence of documentation, I assumed it must be really special. -- _jsn ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: having fun with GADT's
On Mon, Sep 22, 2008 at 11:10 PM, Anatoly Yakovenko [EMAIL PROTECTED] wrote: type One = S Z type Two = S One etc. why does: data Nat a where Z :: Nat a S :: Nat a - Nat (S a) data Z data S a type One = S Z n00 = Z n01::One = S n00 give me: test.hs:10:11: Couldn't match expected type `One' against inferred type `Nat (S a)' In the expression: S n00 In a pattern binding: n01 :: One = S n00 Failed, modules loaded: none. or better yet, how is type S Z different from, n01 :: forall a. Nat (S a) In short, S Z is a type and n01 is a value. One point that's important to keep in mind is that types and data constructors have disjoint namespaces, so you can have a type Z and a data constructor Z which do not need to have any connection. It may be clearer if we rename the data constructors for Nat. data Z data S n type One = S Z data Nat :: * - * where Zero :: Nat Z Succ :: Nat n - Nat (S n) one :: Nat One one = Succ Zero Similarly, One is a type (One :: *) and one is a value (one :: Nat One and Nat One :: *). Note also that Z and S are declared here as empty types, using a common extension. That means there are no (non-bottom) values that have type Z or S a. This means that Z and S are only used as arguments to other type constructors or in class contexts. As long as we're discussing type-level naturals, you may find this old post of mine interesting. http://www.haskell.org/pipermail/haskell/2005-May/015815.html -- Dave Menendez [EMAIL PROTECTED] http://www.eyrie.org/~zednenem/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe