[Haskell-cafe] Re: Is id strict?
David House [EMAIL PROTECTED] writes: Hi all. I've seen two definitions of a 'strict function', which I'm trying to unite in my mind: 1) f is strict iff f _|_ = _|_. 2) f is strict iff it forces evaluation of its arguments. There is a large sticking point that in my minds seems to fit (1) but not (2): id. Clearly, id undefined is undefined, but I also don't think id forces evaluation of its argument. There was a mini-discussion concerning this topic last night on #haskell, but if there was a consensus conclusion, it passed me by. Thanks in advance. In (2), you have to be evaluating f on an argument before f can force the argument. If you evaluate id x, you necessarily evaluate x. I don't think (2) is a very good definition, since I don't know what forces means here. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Is id strict?
Duncan Coutts [EMAIL PROTECTED] writes: On Sun, 2006-07-30 at 10:56 +0100, Jón Fairbairn wrote: David House [EMAIL PROTECTED] writes: 1) f is strict iff f _|_ = _|_. 2) f is strict iff it forces evaluation of its arguments. In (2), you have to be evaluating f on an argument before f can force the argument. If you evaluate id x, you necessarily evaluate x. I don't think (2) is a very good definition, since I don't know what forces means here. Surely it just means evaluate to weak head normal form? Means [what] evaluate[s] to whnf? id doesn't do any evaluating, in fact functions in general don't do any evaluating. Definition 2) relies on following a certain evaluation strategy: that operationally, functions always return results in weak head normal form. GHC follows this strategy. It's possibly to imagine returning thunks and then getting the caller to force the evaluation to WHNF. Which is pretty much my point. Use a definition of strict that doesn't depend on anything but denotations (or Böhm trees). -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Why Not Haskell?
Stefan Monnier [EMAIL PROTECTED] writes: I can't entirely dismiss GNU/FSF/GPL but it poses a fundamental conflict with the only way I can see of earning a living so it's like a continuous background problem which drains some of my energy and enthusiasm hence the length of my rambling post where I made another attempt to understand my relation to it. Maybe you should thank the FSF for making you doubt: you should really think very hard about how you're going to make a living off of selling a program, even if that program hasn't been anywhere near any GPL'd code. In all likelihood it'll be much easier to earn your money by selling services around your program than just the program itself. To add to that from the point of view of a potential user: if there some programme that I'm going to rely on and its source is not free, I'll look elsewhere rather than rely on a single vendor that might disappear without a trace and leave me with no support. Conversely, if it has free source, but doesn't quite do what I'm relying on it to do, I'll happily pay someone to sort it out for me (assuming that I can't/don't want to/am to busy to do it myself and that I have any money). I know of several good ideas that started out as attempts at commercial projects but weren't taken up. The best that happened to them is that someone recoded the idea (or it was re-released) as free software. If that didn't happen, they disappeared without trace. Remember, keeping the code secret is no protection against someone rewriting the whole thing from scratch. If it's a big enough idea, you can be sure that some large commercial concern (and conceivably teams of amateurs) will do that unless you've patented something crucial... and keeping patents alive is an expensive business -- especially if there's a large concern on your case (we want to use your patented idea. Oh, it looks like your code uses one of our patented ideas; you'll be hearing from our lawyers). -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-07-14) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Int-[Char] conversion
Tamas K Papp [EMAIL PROTECTED] writes: Hi, I am working through Hal Daume's tutorial, trying to do the exercises. I can't figure out how to output an integer with putStrLn (or any other way), I think I need an Int - [Char] conversion but couldn't find it. Specifically, in Exercise 3.10, I have the product of numbers in pp, and would like to do putStrLn (Product: ++ convertnumbertostring(pp)) but I don't know which function does this... You could try Hoogle URL: http://haskell.org/hoogle/ , though entering Int - [Char] isn't very helpful, if you put in Int - String, you get 'show' as the second hit, and that's the function you want. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
Stefan Monnier [EMAIL PROTECTED] writes: I'd have thought it would have been simpler to just make the rule that -2 (no spaces between '-' and '2') would be a single lexeme, But then x-2 won't mean subtract 2 from x but call x with arg -2. Well, since the normal typographical convention is that hyphenated-words are read as closely connected, I've always been in favour of including hyphen in variable names and using spaces to separate them from tokens, so perhaps it should just mean the identifier 'x-2'. Though in the days of Unicode we could get round the whole thing by using code 0x002d for unary minus, 0x2010 in identifiers and 0x2212 for infix minus... and spend many a happy hour trying to tell which of the three was intended by some short horizontal line. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-07-14) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [Parsec] No identEnd in ParsecToken?
Stephane Bortzmeyer [EMAIL PROTECTED] writes: On Tue, Sep 05, 2006 at 04:17:41PM +0200, Stephane Bortzmeyer [EMAIL PROTECTED] wrote a message of 25 lines which said: I'm trying to use Parsec for a language which have identifiers where the '-' character is allowed only inside identifiers, not at the start or the end. I'm not really familiar with Parsec (I wrote my own limited backtrack parser years ago, and haven't quite got round to updating my brain), and while (judging by threads like this one) it seems to be harder to use than one would hope, this particular problem doesn't look as hard to me as all that. [My grammar was underspecified, I also want to disallow two consecutive dashes.] [...] Here is my final version (rewritten in my style, errors are mine and not Udo's), thanks again: inner_minus = do char '-' lookAhead alphaNum return '-' identifier = do start - letter rest - many (alphaNum | try inner_minus) return (start:rest) ? identifier I'd have thought something like the following was the 'obvious' way of doing it: chThen c r = do a - c; as - r; return (a:as) identifier = do start - letter `chThen` many alphaNum; rest - many (char '-' `chThen` many1 alphaNum) return (start++concat rest) ? identifier ie, your identifiers are an initial sequence of non-minuses beginning with a letter, and then an optional sequence of non-minuses preceded by a minus. Or have I lost the plot somewhere? Aside: Is there already name for `chThen`? ie (liftM2 (:)); I had a feeling we were avoiding liftM friends for some reason. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-07-14) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: how do you debug programs?
Tamas K Papp [EMAIL PROTECTED] writes: I would like to learn a reasonable way (ie how others do it) to debug programs in Haskell. Is it possible to see what's going on when a function is evaluated? Eg in f a b = let c = a+b d = a*b in c+d evaluating f 1 2 would output something like f called with values 1 2 c is now (+) a b = (+) 1 2 = 3 d is now (*) a b = (*) 1 2 = 2 But why should c and d exist at runtime? They're only used once each, so the compiler is free to replace f with \a b - (a+b)+ a*b and indeed, it's quite likely that f should disappear too. So if your debugger outputs what you want, it's not debugging the programme that you would otherwise have run. Or maybe I am thinking the wrong way, and functional programming has its own debugging style... I've said this before, but I think it's worth repeating: in most cases, if you need to debug your programme it's because it's too complicated for you to understand, so the correct thing to do is to simplify it and try again. That's not to say that I don't think you should test programmes... in fact I'm all for testing little bits. You can define f above and try it on a few arguments in ghci or hugs, and you can use QuickCheck and/or HUnit to automate this. But there's no reason for you to care what happens while f is evaluating. Remember there's very little (often no) overhead for defining subsidiary functions, so break complicated stuff into parts you can understand. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-07-14) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: how do you debug programs?
Neil Mitchell [EMAIL PROTECTED] writes: Hi But why should c and d exist at runtime? They're only used once each, so the compiler is free to replace f with \a b - (a+b)+ a*b Yes, and if the compiler is this clever, it should also be free to replace them back at debug time. And where does that get us? You snipped the salient bit where I said that you'd be debugging a different programme. If the debugger serialises stuff and refers to variables, it reinforces an imperative view of the world and supports the erroneous view of variables as things that exist at runtime. AFAIK, no implementation nowadays compiles to pure combinators, but such would still be a valid implementation of Haskell. You need to develop a way of thinking about programmes that produces insights that apply to Haskell, not to a particular implementation. I've said this before, but I think it's worth repeating: in most cases, if you need to debug your programme it's because it's too complicated for you to understand, so the correct thing to do is to simplify it and try again. That makes it impossible to ever improve - initially all programs are beyond you, and only by pushing the boundary do you get anywhere. I offer myself as a counter example. I'm not the world's best Haskel programmer (that might be Lennart?;-), but I understand it pretty well, I think. At no point have I ever used a debugger on a Haskell programme. So clearly not impossible (I didn't come into existence a fully fledged functional programmer, which is the only other possibility admitted by your argument). As for me, I always write programs I can't understand, and that no one else can. Perhaps I understood it when I originally wrote it, perhaps not, but that was maybe over a year ago. No comment. It's been my experience that debugging is a serious weakness of Haskell - where even the poor mans printf debugging changes the semantics! And everyone comes up with arguments why there is no need to debug a functional language - that sounds more like excuses about why we can't build a good lazy debugger :) It may sound like that to you, but the arguments why debugging is a bad thing are quite strong. There are almost certainly bugs in my Haskell code. Would a debugger help me find them? Not in the least, because none of the testcases I've used provokes them. Would it help when one is provoked? I don't think so, because either the logic is right and there's a slip up in the coding, which is usually easy to find from the new testcase, or the logic is tortuous and needs replacement. [Sorry for the slight rant, but I've used Visual Studio C++ so I know what a good debugger looks like, and how indispensable they are] So I'm ranting back at you. I've used debuggers on C and other old languages (particularly when writing in assembler) and indeed they are useful when the language provides so many opportunities for mistakes. When writing Haskell I've never felt the need. Here's a story: A long time ago, when I was an undergraduate, I encountered a visitor to the Computing Service who often asked for help with the idiosyncrasies of the local system. I was happy to help, though somewhat bemused by all the muttering at his terminal while he was programming, which involved some sort of debugging, for sure. After some weeks he finished his programme and whatever kept him in Cambridge and disappeared. Being curious, I dug (strictly against regulations) a listing of his programme out of the scrap bin. It was in PL/I, and several millimetres thick. It took me quite a while (hours, though, not weeks) to work out what the programme did, but eventually I understood it well enough that I could write a version in Algol68 (my favourite language at the time). It came to one sheet of listing paper. This wasn't because A68 is more expressive than PL/I (it is, but not by that much), it was because I understood the problem before I started to write the code. Now, you could argue that the first programmer spent most of his time working out what the problem was (it might even be true, but given that it boiled down to 1 page of A68, I'm not sure), but my point is that if you proceed by debugging rather than rewriting, you are likely to end up with this sort of mess. Personally, I don't mind too much if that kind of programmer finds Haskell too hard. Elitist? Certainly! Immorally so? No. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-07-14) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: how do you debug programs?
Tamas K Papp [EMAIL PROTECTED] writes: On Wed, Sep 06, 2006 at 06:33:32AM -0400, Lennart Augustsson wrote: I've also used Visual Studio, and I wouldn't mind having something like that for Haskell. But I have to agree with Jon, I think the best way of debugging is to understand your code. I think people who come from imperative programming come with a mind set that you understand your code by stepping through it in the debugger. But I find this paradigm much less useful for functional code. At this point, I need debugging not because I don't understand my code, but because I don't understand Haskell ;-) Most of the mistakes I make are related to indentation, precedence (need to remember that function application binds tightly). The compiler and the type system catches some mistakes, but a few remain. I don't think you need a debugger for that. In addition to what Lennart and Ketil have said, I think you need to take on board the usefulness of breaking functions up into small pieces that can be run at the GHCi or Hugs command line. And if you aren't sure about precedence, you can type something that demonstrates it, like this sort of thing: *Main let f = (+1) *Main f 1 * 2 4 (That particular example only works in GHCi, but you could use let f = (+1) in f 1 * 2 in Hugs) On top of that, in GHCi you can do this: *Main :info + class (Eq a, Show a) = Num a where (+) :: a - a - a ... -- Imported from GHC.Num infixl 6 + *Main :info * class (Eq a, Show a) = Num a where ... (*) :: a - a - a ... -- Imported from GHC.Num infixl 7 * *Main Note in particular the two infixl lines, which say that both operators bind to the left and that “*” binds more tightly than “+” And there's always Hoogle (and the documentation it links to) if you want to find something of a particular type. Kudos to Neil for producing this, by the way (though I do hope his remarks about the readability of his code were a more self deprecating than accurate). -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: how do you debug programs?
Neil Mitchell [EMAIL PROTECTED] writes: Hi Yes, and if the compiler is this clever, it should also be free to replace them back at debug time. And where does that get us? You snipped the salient bit where I said that you'd be debugging a different programme. In Visual C there are two compilation modes. In debug mode, if you create a variable i it WILL be there in the compiled version. It won't be merged with another variable. It won't be constant folded. It won't have its value globablly computed and stored. It won't be placed only in the register. In release mode all these things can (and do) happen. I'm not saying Haskell compilers aren't free to optimize, but maybe there is a need for one that is this debug mode style. I think this chiefly indicates that you think of variables as things, which in Haskell they are not. At no point have I ever used a debugger on a Haskell programme. Because you couldn't find a working debugger? ;) If one had been there, just a click away, would you never have been tempted? Not in the least. The highest level language I've ever wanted to use a debugger on was C, and that was for debugging a pointer-reversing garbage collector, which ties in with what Andrae says. Let take for example a bug I spent tracking down in Haskell this weekend. The bug can be summarized as Program error: pattern match failure: head []. And indeed, thats all you get. A quick grep reveals there are about 60 calls to head in the program. In this instance I have the choice between 1) crying, 2) a debugger, 3) a lot of hard work. [Of course, knowing this situation arises, I had already prepared my getout plan, so it wasn't a massive problem] H'm. I've never been completely convinced that head should be in the language at all. If you use it, you really have to think, every time you type in the letters h-e-a-d, “Am I /really/ /really/ sure the argument will never be []?” Otherwise you should be using a case expression or (more often, I think) a subsidiary function with a pattern match. Most of the occurrences of “head” in my code seem to be applied to infinite lists, or commented out, or rebindings of head to something else, sloppy bits of nonce programming or references in comments to the top of my own noddle. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-07-14) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] head c Re: how do you debug programs?
Neil Mitchell [EMAIL PROTECTED] writes: I wrote: H'm. I've never been completely convinced that head should be in the language at all. If you use it, you really have to think, every time you type in the letters h-e-a-d, Am I /really/ /really/ sure the argument will never be []? Otherwise you should be using a case expression or (more often, I think) a subsidiary function with a pattern match. I disagree (again...) - head is useful. Given that a programming language remain computationally complete, utility is never a sufficient reason for including something in it. Guns are occasionally useful, but if you walk around with a loaded automatic down the front of your pants, you are *far* more likely to blow your own balls off than encounter circumstances where the gun would be useful. A large part of good programming language design is about preventing you from blowing your balls off (or anyone else's). And as you go on to say, if you apply it to the infinite list, who cares if you used head. Head is only unsafe on an empty list. So the problem then becomes can you detect unsafe calls to head and let the programmer know. No, that's the wrong approach because it relies on detecting something that (a) the programmer probably knows already and (b) is undecidable in general. It would be far better for the programmer to express this knowledge in the programme. In Haskell it's not possible for the two datatypes data NonFiniteList t = (:) {head::t, tail:: NonFiniteList t} and data List t = (:) {head::t, tail:: List t} | [] to coexist, and though it would even then have been possible to use a type system where all the operations on List were also applicable to NonFiniteList, the means available then would have lost type inference. So the consensus at the time was that doing clever stuff with types (making one a transparent supertype of the other) was too problematic, and keeping them separate would have meant providing all the list operations twice. Once typeclasses came along, this argument no longer held, but redoing lists and nonfinite lists as special cases of a sequence class would have been hard work. I think it's hard work that should have been done, though. As I said in the post to which you replied, if you use head, you really have to have a convincing argument that it isn't going to be applied to []. If you don't have one, use something other than head (it's always possible). If your programme crashes with a head [], the only reasonable thing to do is to go through all 60 uses and check them. If you don't have time for that right now, doing an automatic replace is a reasonable interim measure, so long as you don't replace them back once you've found the particular bug. 1 i import Control.Exception . s/head/(\l - assert (not $ null l) (head l))/g ... Ugly, and *** Exception: /tmp/foo.hs:4:7-12: Assertion failed is really ugly, but not as ugly as *** Exception: Prelude.head: empty list :-) And the ugliness might encourage a rethink of particular uses of head next time you have to look at that bit of code, and that's a good thing even if all you end up doing is manually substituting a let for the lambda and adding a comment on the lines I really can't see how this list could ever be empty, but I can't prove it. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: how do you debug programs?
Claus Reinke [EMAIL PROTECTED] writes: thinking helps, but claiming that tools can't help doesn't. Lets be absolutely clear about this: I've never claimed that tools can't help. In this thread I've been using the term debugger in the narrow sense implied by the OP's question -- something that steps through the execution of the code. Such a debugger is inappropriate for Haskell programmers, and doubly so for beginners. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: how do you debug programs?
David Roundy [EMAIL PROTECTED] writes: On Wed, Sep 06, 2006 at 09:56:17AM -0700, Jason Dagit wrote: Or maybe even more extreme you could use template haskell or the c preprocessor to fill in the line number + column. Which is precisely what darcs does for fromJust (which we use a lot): we define a C preprocessor macro fromJust. Curiously, the only bug in darcs that has bitten me so far was a use of fromJust. Perhaps that indicates a weakness in the style, rather than the tools? -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
Cale Gibbard [EMAIL PROTECTED] writes: Another thing to note is that all the natural literals are not, as one might initially think, plain values, but actually represent the embedding of that natural number into the ring (instance of Num), by way of 0 and 1. I wasn't sure where to add this, so here will have to do: I think the present design is wrong because we don't have a type for naturals. So in my view, “-1” should be “negate (fromNatural 1)” -- whatever names we use for those two functions. I can't remember right now why the early versions of Haskell didn't have a Natural type, or what makes it difficult to change to now (and I think this is something we really should do), but even given that, I think the present special casing of “-” is a reasonable compromise. Given a built in Natural type, it makes no sense to have “-” as part of the syntax for literals, since Natural literals don't have it and there's no way to add more constructors (ie negative literals) onto an existing type to get Integer, but having a symbol for negate does it in a straightforward way. * ** * For my own taste, I would have “-” as a character that can appear in identifiers and operators (but special in that if it appears at the beginning it cannot be followed by anything? Otherwise -1 would just be an identifier!) and define - n = negate n a +- b = a + (- b) but I think that most people would baulk at having to use “+-” for infix minus. People would similarly baulk at the opposite tack of making “-” solely infix and using something else for negate (as in ML), although finding a different token (such as “__”) for don't care and using “_” for unary minus doesn't seem too bad to me. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
. At some point in the future someone might decide that or % is needed to introduce a new chunk of syntax, and formerly valid programmes break. So why not just say that varsym varid is in general reserved for future special syntaxes, and require varsym whitespace varid everywhere? -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-07) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: sections of noncommutative operators
Michael Shulman [EMAIL PROTECTED] writes: A propos of sections of subtraction, and thence to sections of other noncommutative operators, as a Haskell newbie I was surprised to discover (the hard way!) that ( 0) and (() 0) mean different things. I had typed ( 0) when I meant to type (() 0). No compiler errors, of course, and I had a devil of a time finding that bug. My initial reaction was that ( 0) should be an error and you should have to write (() 0); now I realize that the section notation is more fundamental, since () itself is actually a double section. And of course I should have written ( 0) anyway; Well, this is the first time I've noticed anyone mention it! If you appreciate sections, you read ( 0) as less than zero, and the meaning is clear. I don't think it takes much in the way of mental gymnastics to do that, since you just read the tokens in order. it's probably my lisp background that tripped me up. I should think so. But does lisp have currying these days? (lessp 0 1) == T but (lessp 0) would be an error, wouldn't it? But is there any way this could be made less confusing? Right about the start of the design of Haskell, I proposed the rule parentheses should only be used for grouping. If we had adopted that, you wouldn't have been confused by sections, because sections would have had to use a different syntax. However, while I was reluctant to lose the rule, sections in their present form do have a great deal to be said for them. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-07) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
Aaron Denney [EMAIL PROTECTED] writes: We already have this great syntax, parsing semanticsi for precedence, and so forth for declaring infix operators. Couldn't we add to that slightly by declaring postfix operators as well? Actually, declaring a unary operator infix yielding a postfix operator doesn't seem like too much abuse. Possibly not, provided they're always used as sections. (e #) already always means supply e as the first argument to (#)). (I haven't thought this through to any great extent. How much would it complicate parsing? Not much, I would assume, as this fails in ghc at the type-checking stage.) I don't think it would complicate mechanical parsing unreasonably. I do think (if done without the parentheses) it might complicate /human/ parsing unreasonably. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-07) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
Aaron Denney [EMAIL PROTECTED] writes: Jón Fairbairn [EMAIL PROTECTED] wrote: I think the present design is wrong because we don't have a type for naturals. Meh. Naturals are reasonably useful sometimes, but not often enough, in my opinion. Any sort of numeric hierarchy designed to deal with them would be totally broken from my point of view -- if you don't at least have inverses, it's not a number, Crikey. Would you really have me accept that the natural numbers aren't numbers? just some sort of weird algebraic structure. And if it's not in the numeric hierarchy, and so you can't do arithmetic syntactically nicely with it, what's the point? Could you elaborate? I haven't thought it through, but I can't see why splitting Num into something that puts Natural above Integer would be particularly problematic. Natural just has fewer operations than Integer. It doesn't have “-”, but it does have “difference:: Natural - Natural - Natural”, and so do the bigger types (“difference a b = abs (a - b)”) Is it better to make (^^), (^), and take partial functions, or to make (-) and negate partial functions? No :-). “-” and “negate” would belong to a class of which Natural had no instances. If you're the sort of person who likes having partial functions like “head” sullying the scene, you might find it convenient to have “integralToNatural” that either returns the corresponding Natural or throws an exception. Actually, if you are someone like that, you probably want to give it a shorter name... Of course, there's always a typeclass, where we could add all sorts of other encodings of the Peano axioms, such as binary trees,, but I don't see that that buys us much if we don't also get access to operations beyond them, such as (an _efficient_) `div` for fastexp. I don't see why Natural can't have an instance of whatever class ends up owning “div”. It's perfectly well behaved on Naturals. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-07) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
Aaron Denney [EMAIL PROTECTED] writes: On 2006-09-08, Jón Fairbairn [EMAIL PROTECTED] wrote: Why shouldn't Naturals be more primitive than Integers? Certainly they're more primitive. Too primitive to have reasonable algebraic properties. Hmph. Naturals obey (a+b)+c == a+(b+c), which is a nice and reasonable algebraic property that Float and Double don't obey. In fact Float and Double have lots of /un/reasonable algebraic properties, but we still have them in the language. (I think they should be turfed out into a numerical library). -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-07) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
Brian Hulley [EMAIL PROTECTED] writes: Jón Fairbairn wrote: [1] “-” is a varsym. The logical way of achieving what you suggest (ie -1 -2... as constructors for Integer) would be to make it introduce a consym the way “:” does, but then it couldn't be an infix operator anymore. I don't think it's necessary to use the same kind of rule for '-' as for ':'. Not necessary, but you surely don't want yet another rule? I imagine that almost every editor at least does lexical fontification, and if so, then I don't think there could be much confusion in practice between these uses of '-'. I think that unnecessarily disadvantages people with poorer than average (including zero) eyesight. Yes, a typeclass for exp would be ideal Well, so long as you call it “exponent” or “expt”. (and a newtype for Natural). Here's a design principle for you: if an error can be detected at compile time, it should be. If we have literals for naturals and not negative integers, “negate 100” causes no problem, it just means “negate (fromNatural 100)”. If we have literals for integers and try to restrict them to get naturals, “-100:: Natural” becomes shorthand for “integralToNatural (-100)”, and would (in the absence of somewhat arbitrary special-casing in the compiler) give a runtime error. I also agree with Tamas's suggestion that an empirical analysis of Haskell source code could be useful to determine the practical implications of unary minus, It has merit and I would laud anyone who got round to doing it, but there's a danger of measuring the wrong thing. What we want to know is not what is more frequent, but what causes the greater number of misreadings and which pieces of code had the most syntax errors before they were completed, and that's harder to measure. Though if unary minus turned out to be very rare, we could just drop it. Using “(0-)” wouldn't be much of a hardship in that case. Anyway no doubt I've posted enough emails about unary minus and negative literals so I'll be quiet now ;-) :-) ... ? -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Problems interpreting
Andrea Rossato [EMAIL PROTECTED] writes: On Mon, Sep 18, 2006 at 04:16:55AM -0700, Carajillu wrote: Wow! I'm starting to love this languaje, and the people who uses it!:) You spoke too early. My code had a bug, a huge one... this is the right one: -- Replaces a wildcard in a list with the list given as the third argument substitute :: Eq a = a - [a] - [a] - [a] substitute e l1 l2= [c | c - check_elem l1] where check_elem [] = l1 check_elem (x:xs) = if x == e then (l2 ++ xs) else [x] ++ check_elem xs I think it's nicer to do it like this: substitute e l l' = concat (map subst_elem l) where subst_elem x | x == e = l' | otherwise = [x] since subst_elem has a more straightforward meaning than check_elem, and the concatenation is handled by a well known standard function. Also, it would usually be more useful to have the argument to replace /with/ before the argument to replace /in/, so that (substitute '*' wurble) is a function that replaces all the '*'s in it's argument with wurbles. And if you do that, you can write it like this: subst e l' = concat . map subst_elem where subst_elem x | x == e = l' | otherwise = [x] -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Problems interpreting
Andrea Rossato [EMAIL PROTECTED] writes: On Mon, Sep 18, 2006 at 12:42:59PM +0100, Jón Fairbairn wrote: And if you do that, you can write it like this: subst e l' = concat . map subst_elem where subst_elem x | x == e = l' | otherwise = [x] Pretty. Just to many keystrokes. Keystrokes? Learn to touchtype! This should take two keystrokes less, probably: subst e l [] = [] subst e l (x:xs) = if x == e then l ++ xs else x : subst e l xs but if you want short, do this: subst e l' = concat.map (\x-if x==e then l' else [x]) which beats yours by twenty seven characters and one bug ;-P -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-13) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Java or C to Haskell
Carajillu [EMAIL PROTECTED] writes: That works good, but I have a problem with the return type, I forgot to mention... can it be a [char]?? If that's what you want, how about this: import Maybe find_match l1 l2 c = fmap catMaybes . sequence $ zipWith match l1 l2 where match a b | a == c = Just (Just b) | a == b = Just Nothing | otherwise = Nothing although part of the reason for writing it like that is to make you work hard to understand it ;-) ... and it returns Maybe [Char] since I can't bring myself to use to indicate failure... but judicious use of catMaybes . concat. maybeToList might help with that. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [newbie] How to test this function?
Bruno Martínez [EMAIL PROTECTED] writes: On Thu, 21 Sep 2006 15:12:07 -0300, Benjamin Franksen [EMAIL PROTECTED] wrote: OK. Thanks. I didn't find that one because it's not offered as an identation option in emacs haskell mode. Emacs is evil! That's a great exaggeration I'm open to alternatives. I use Windows, so went out of the way to have emacs. What do you use? I don't care much for colors, but automatic identation is very handy (when it works :D). If there's a problem with haskell emacs mode, it seems very likely that if you ask the maintainer nicely, he'll do something about it. See http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-13) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [newbie] How to test this function?
Johan Tibell [EMAIL PROTECTED] writes: If there's a problem with haskell emacs mode, it seems very likely that if you ask the maintainer nicely, he'll do something about it. See http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode I asked Stefan a while ago: I like your Emacs mode but it behaves a bit oddly when trying to indent if/then/else expressions in do notation. Typing tab only gives me one possible indentation, like so: do if True then foo else bar That is, the then and else branches line up under the if which is an error according to Haskell's layout rule. It probably should indent them like case with the then lining up with the condition to the if. I'd fix it myself if I knew Lisp but I don't. :/ Yes, it's a (recently) known problem which I haven't fixed yet. It's in the indent.hs test-suite, with a FIXME :-( For that one, if it doesn't get mended for long enough, Haskell' might accept the present layout. http://hackage.haskell.org/trac/haskell-prime/wiki/DoAndIfThenElse -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-13) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Haskore
David Curran [EMAIL PROTECTED] writes: Hi I have been trying to learn haskell (tip over the vending machine) Tipping over a vending machine is a real world effect, so you'll have to use the IO Monad. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Haskell compiler from a USB Stick?
Bulat Ziganshin [EMAIL PROTECTED] writes: Hello David, Tuesday, October 3, 2006, 2:17:33 PM, you wrote: Does anyone know of a Haskell compiler that will run from a USB stick? i'm ôäüùûå sure Блым? -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Haskell performance (again)!
Brian Hulley [EMAIL PROTECTED] writes: Lennart Augustsson wrote: I think your first try looks good. [snip] ... addPoly1 p1@(p1h@(Nom p1c p1d):p1t) p2@(p2h@(Nom p2c p2d):p2t) | p1d == p2d = Nom (p1c + p2c) p1d : addPoly1 p1t p2t | p1d p2d = p1h : addPoly1 p1t p2 | p1d p2d = p2h : addPoly1 p1 p2t ... The last comparison is redundant (this was in the original version too) because p1d p2d is implied (certainly for this case where p1d, p2d::Int) by the fall through from not satisfying == and so how about: addPoly1 p1@(p1h@(Nom p1c p1d):p1t) p2@(p2h@(Nom p2c p2d):p2t) | p1d == p2d = Nom (p1c + p2c) p1d : addPoly1 p1t p2t | p1d p2d = p1h : addPoly1 p1t p2 | otherwise = p2h : addPoly1 p1 p2t Surely all but one of the comparisons is unnecessary? If you use `compare` instead of (==) and friends, won't one do (I'm assuming that the compiler can convert cases on LT, EQ and GT into something sensible -- after all, wasn't that the purpose of compare?)? -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-13) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Debugging Newton's method for square roots
Vraj Mohan [EMAIL PROTECTED] writes: I am new to Haskell and need help in debugging my code. I wrote the following function for calculating square roots using Newton's method: my_sqrt :: Float - Float my_sqrt x = improve 1 x where improve y x = if abs (y * y - x) epsilon then y else improve ((y + (x/y))/ 2) x epsilon = 0.1 This works for several examples that I tried out but goes into an infinite loop for my_sqrt 96. Generally it's better to separate out the different parts of the algorithm. So sqrt_step x candidate = (candidate + x/candidate)/2 Now you can try take 20 $ iterate (sqrt_step 2) 1 and watch the convergence. When you're happy with that, you can use something like “head . dropWhile unconverged”. (The equivalent code is well-behaved on MIT Scheme) Is it? Is there equivalent code to “my_sqrt :: Float - Float”? (that might be pertinent). -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-13) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Debugging Newton's method for square roots
I wrote: Vraj Mohan [EMAIL PROTECTED] wrote: (The equivalent code is well-behaved on MIT Scheme) Is it? Is there equivalent code to “my_sqrt :: Float - Float”? (that might be pertinent). By which I mean HINT. (And one of the places to look for bugs is where you have hand coded a constant without due consideration of the implications). -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-13) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Automatic fixity allocation for symbolic operators
Nicolas Frisby [EMAIL PROTECTED] writes: What if operator precedences were specified as a partial order instead of using numbers? I suggested something that did that to fplangc back in 1987... Thu, 19 Nov 87 17:49:50 GMT in fact! Simon PJ later forwarded a message from Stef Joosten to similar effect... I made a more concrete proposal later and Phil Wadler tidied it up. I think It even got as far as a draft of the language, but I think it was decided that it was just too difficult (both for human and computer) to parse. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-13) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Automatic fixity allocation for symbolic operators
Nils Anders Danielsson [EMAIL PROTECTED] writes: On Mon, 16 Oct 2006, Jón Fairbairn [EMAIL PROTECTED] wrote: I made a more concrete proposal later and Phil Wadler tidied it up. I think It even got as far as a draft of the language, [...] Do you know where this proposal/draft can be found? On the fplangc mailing list. Thomas Johnsson has the archive, but as it was a closed mailing list I don't know if it's OK to publish the URL. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: split string into n parts
jim burton [EMAIL PROTECTED] writes: Paul Brown-4 wrote: Cool idea! Can you post a link for the puzzles? Thankyou! It's http://www.rubyquiz.com - They are mostly well suited to haskell, lot of mazes etc. I've done 5 or 6 with varying degrees of success but have learned a lot. This thing about strings in fifths is from #1, the solitaire cipher. At a quick glance I can't see which bit needs it. The only mention of five is where it asks to split the string into groups of five characters (not into five equal parts), padded with Xs. You can do that like this: splitAtMb n l = let p = splitAt n l in if null $ fst p then Nothing else Just p in_fives l = unfoldr (splitAtMb 5) (l ++ replicate (length l `mod` 5) 'X') To break a string into five equal parts with the last padded with Xs, try this: fifths l = let len = length l part_length = (len+4)`div`5 pad_length = 5*part_length - len in unfoldr (splitAtMb part_length) (l ++ replicate pad_length 'X') I haven't checked these at all carefully, but at least they illustrate the use of unfoldr. [aside: One might argue that the prelude ought to provide splitAtMb rather than splitAt.] -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: split string into n parts
jim burton [EMAIL PROTECTED] writes: tweak to in_fives in_fives l = unfoldr (splitAtMb 5) (l ++ replicate (5 - length l `mod` 5) 'X') Whoops! Yes. And a slapped wrist for me for writing a constant three times. Serves me right for not writing groups_of n l = unfolder (splitAtMb n) ... in_fives = groups_of 5 :-) -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: split string into n parts
I wrote: jim burton [EMAIL PROTECTED] wrote: Thankyou! It's http://www.rubyquiz.com - They are mostly well suited to haskell, lot of mazes etc. I've done 5 or 6 with varying degrees of success but have learned a lot. This thing about strings in fifths is from #1, the solitaire cipher. At a quick glance I can't see which bit needs it. The only mention of five is where it asks to split the string into groups of five characters (not into five equal parts), padded with Xs. You can do that like this: splitAtMb n l = let p = splitAt n l in if null $ fst p then Nothing else Just p Gah! Brain AWOL. I'm surprised no-one picked me up on that. Why didn't I use: splitAtMb n [] = Nothing splitAtMb n l = Just $ splitAt n l ? in_fives l = unfoldr (splitAtMb 5) (l ++ replicate (length l `mod` 5) 'X') And using length makes this over-strict. maybe something like groups_of n = unfoldr (splitPad 5) where splitPad [] = Nothing splitPad l = Just $ mapFst (padwith 'X') (splitAt n l) padwith c l = take n $ l ++ replicate n c mapFst f (a,b) = (f a, b) -- in Data.Graph.Inductive.Query.Monad which is a little bit inefficient, but less clunky than checking for the end of list in order to apply padwith just once. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Solitaire cipher
jim burton [EMAIL PROTECTED] writes: In addition to Chris's comments, here are some more: data Card = Clubs Int | Spades Int | Diamonds Int | Hearts Int | JokerA | JokerB They aren't really Ints; better to define something like data FaceValue = Ace | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | Jack | Queen | King and possibly derive Enum (which unfortunately would give the the wrong values, but that can be got around). deriving (Show, Eq) type Deck = [Card] --cardval - clubs are face value, diamonds plus 13, and so on - Jokers are both 53 I'd be inclined to define an Enum instance rather than cardval directly, but define cardval as an auxilliary function that scrunches both jokers to the same value. isJoker:: Card - Bool isJoker JokerA = True isJoker JokerB = True isJoker _ = False Since you've defined an instance of Eq, you can use isJoker c = c == JokerA || c == JokerB --take a card to a letter card2char :: Card - Char card2char c = case c of (Clubs i)- int2alpha $ cardval c --can case fall through in haskell? It's defined to, but you don't need a case clause as you can use cardval and mod. --take a letter to int, A=1, Z=26 char2int :: Char - Int char2int = (64 `subtract`) . (ord) Better to use (ord 'A' - 1) if you are going to do it this way. --take a letter to int, 1=A, Z=26 int2alpha :: Int - Char int2alpha = (chr) . (+64) and again splitAtMb n l = let p = splitAt n l in if null $ fst p then Nothing else Just p That was my mistake! Use the shorter, cleaner version I posted after that one. in_fives l = foldr (\x y - x++ ++y) [] $ unfoldr (splitAtMb 5) (l ++ replicate (5 - length l `mod` 5) 'X') Putting the spaces in at this point is a mistake! Also see what I said about length. --get an ordered deck newdeck :: Deck newdeck = suit 'c' ++ suit 'd' ++ suit 'h' ++ suit 's' ++ JokerA : JokerB : [] where suit s = case s of 'c' - [Clubs i | i - [1..13]] 's' - [Spades i | i - [1..13]] 'd' - [Diamonds i | i - [1..13]] 'h' - [Hearts i | i - [1..13]] That seems overly complicated. With an Enum instance, you'd just do newdeck = [Club Ace .. JokerB] or better, with an instance of Bounded too, newdeck = [minBound .. maxBound] Of course, you'd have to write toEnum to do the work, but I'd do it something like toEnum 54 = JokerB toEnum 53 = JokerA toEnum n = [Club, Diamond, Heart, Spade]!!suit $ (toEnum (val+1)) where (suit, val) = (n-1) `divMod` 13 Comments from now on are a bit less thought through... I think there are better ways to do some of these operations, but I'm not going to present them, just nitpick a bit instead. --key the deck ready to provide a keystream - move JokerA down one place, --JokerB down 2 places, perform a triplecut then a countcut keydeck :: Deck - Deck keydeck = countcut. triplecut . (movedown JokerB) . (movedown JokerB) . (movedown JokerA) --bump a card down by one place in a deck, treating the deck as circular so if the card is -- last in the deck it becomes 2nd to front not 1st movedown :: Eq a = a - [a] - [a] movedown c d = if c == last d that looks like an unnecessary pass over the list then head d : c : init (tail d) else top ++ bot!!1 : c : (tail (tail bot)) where splt = splitAt (locate c d) d top = fst splt bot = snd splt you can write where (top,bot) = splitAt ... But how about List.break? And if you know that bot is going to have enough elements where (top, card1:card2:rest) = break ... -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Rank N type tutorial?
David House [EMAIL PROTECTED] writes: On 27/10/06, Greg Buchholz [EMAIL PROTECTED] wrote: I thought exists was spelled forall in Haskell? There is some confusion here, It's the notation for data declarations that causes the confusion. To rearrange your text a bit: So, for example: [forall a. a] -- the list whose elements all have the type forall a. a, i.e. a list of bottom. list of bottoms. forall a. [a] -- all elements have some (the same) type a, which can be assumed to be any type at all by a callee. and consequently also must be a list of bottoms. This: data T = forall a. MkT a is where the confusion comes in. This means that: MkT :: forall a. a - T If the standard syntax were data T where MkT :: forall a. a - T (as for GADTs), there's be less of a problem. (it's still misleading, because T looks like it has no variables in it, which might lead one to conclude that MkT throws away its argument) Equally, the natural way of writing it with the old syntax would be: data T = MkT (exists a. a) ie a T is the constructor MkT applied to some unknown type. So people seeing the first form tend to think it means this last. -- which is what you said, but I think this highlights the source of confusion better. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Why is Haskell not homoiconic?
Henning Sato von Rosen [EMAIL PROTECTED] writes: Hi all! I am curious as to why Haskell not is homoiconic? It very nearly is. The icon for Haskell is a lower-case lambda, but the logo for these folk http://www.ualberta.ca/~cbidwell/cmb/lambda.htm is an upper-case lambda. Homiconic means that the primary representation of programs is also a data structure in a primitive type of the language itself Oh, dear, that renders my remark above irrelevant ;-0 The main reason is that Haskell is designed as a compiled language, so the source of the programme can safely disappear at runtime. So there's no need to have a representation of it beyond the source code. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: there's a monster in my Haskell!
David House [EMAIL PROTECTED] writes: On 01/11/06, Andrew Pimlott [EMAIL PROTECTED] wrote: I present here a gentle introduction to monsters. Absolutely brilliant. This certainly made me laugh! Perhaps a light-hearted candidate for the Monad.Reader? And do we have any artistic Haskellers out there? Could we get drawings of these monsters? I'd love to see the 'mysterious and awesome IO' in pictorial form. For that, an image has already (after considerable effort and expense in tracking down the beast) been created: http://tinyurl.com/yddv4z -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Fractional/negative fixity?
Simon Marlow [EMAIL PROTECTED] writes: Nicolas Frisby wrote: Let's remember that if something is broke, it's only _right_ to _fix_ it. I patiently waited for someone else to make that pun. Understanding the language won't be much harder, but understanding fixity declarations will become a task. Consider: infixl -1.7521 -- what and why? As the operator space becomes more dense, negative and fractional fixities are going to become more obfuscated. The negative and fractional fixities will satisfy a number purposes well, but they will also be abused and lead to confusion. This smells like a wart growing on a wart to me. All these are valid points. However, given that we can't completely redesign, implement and test a new fixity system in time for Haskell', ...the correct thing to do is to leave it alone, rather than make a change that addresses only one of the problems. it makes sense to make a simple change that unambiguously improves the current system, I dispute that. It does make it possible to introduce a new operator between two others, but on its own, that strikes me as as likely to be a new problem as an improvement because of the difficulty of remembering numeric precedences. It's bad enough with the present number, let alone a countable infinity of them. The biggest flaw in the present system (and something I wanted to address in my original proposal way back when) is that there is no way to state that there is /no/ precedence relationship between two operators. It would be far better to have the compiler give an error message saying that an expression needs some parentheses than have it choose the wrong parse. The next smaller flaw is that numeric precedences are a poor match for the way we think. I can easily remember that (*) binds more tightly than (+), or that (+) beats (:) (though the latter is slightly less obviously correct), but I don't remember the numbers so when I want to define something new that has a similar precedence to (*) (some new kind of multiplication), I have to look it up, which is tedious. Wanting to insert an operator between two others comes lower in importance even than that, because in many cases giving it the same precedence as something and appropriate associativity gets you most of the way there. It bites because you can't say you want an error if you use it next to something else without parentheses. Let me throw out a couple of possibilities differing only in syntax (one of my fears is that if we get fractional fixities the other problems will be forgotten, so a real improvement will never be discussed). I don't expect either of them to go into Haskell', but putting them forward might encourage further discussion and discourage introduction of something temporary that will stay with us forever. Syntax 1, based on Phil Wadler's improvement of my old proposal. The precedence relation is a preorder. infix {ops_1; ops_2; ...; ops_n} (where each ops is a collection of operators optionally annotated with L or R) would mean that each operator in ops_i binds more tightly than all the operators in ops_j for ji. (and we require ops_i `intersect` ops_j = empty_set for i/=j) Layout rule applies for {;...}. An op can be a varsym or a backquoted varid. It says nothing about the relationship between the those operators and operators not mentioned, except by virtue of transitivity. So infix R ^ L * / L + - would replicate the current relationships between those arithmetic operators. An additional declaration infix + R : says that (+) binds more tightly than (:) and by transitivity, so do (^ * and /). The associativity label obviously has to be the same for all occurrences of an operator in scope, so omitting it just says that it's specified elsewhere. infix * R @+ @- + says that (@+) and (@-) fall between (*) and (-), and that (a @+ b @- c) parses as (a @+ ([EMAIL PROTECTED])) but infix * R @@ says that (a * b @@ c @@ d) parses as ((a*b) @@ (c@@d)) but leaves (a + b @@ c) undefined (a compile time error) unless another declaration specifies it elsewhere. And infix R @@ @@@ says nothing about the relationship between @@ or @@@ and other operators, but indicates that they associate to the right individually and together. The alternative syntax is exemplified thus: infix L + - (L * / (R ^)) The precedence increases the more deeply you go into the parentheses. Arguably this is more suggestive and avoids the possibility of reading precedences as increasing down the page (danger of endianism argument cropping up there!), but may be harder to read. With both syntaxes there's no reason to reserve L and R, since the context disambiguates. For exports (imports) you pass the graph of the relation with the unexported (unimported) operators omitted. and is no more difficult to implement (in fact, I bet it adds zero lines of code to the compiler). If ease of implementation had been a
[Haskell-cafe] Re: Debugging partial functions by the rules
Simon Peyton-Jones [EMAIL PROTECTED] writes: | The problem I see is that head/fromJust errors are usually |caused by *beginner* Haskellers, who don't know the |techniques for statically avoiding them. I don't agree. My programs have invariants that I can't always express in a way that the type system can understand. E.g. I know that a variable is in scope, so searching for it in an environment can't fail: head [ v | (n,v) - env, n==target ] (Maybe if I had an Oleg implant I could express all this in the type system -- but I don't.) But instead of “blah (head [ v | (n,v) - env, n==target ]) blah”, you could write blah the_v_in_scope blah where (the_v_in_scope:_) = [ v | (n,v) - env, n==target ] and get a source-code located error message, couldn't you? It's not very high tech, but it's what you would write if head didn't exist, and it doesn't seem /that/ great an imposition. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Debugging partial functions by the rules
Neil Mitchell [EMAIL PROTECTED] writes: Hi Haskell is great for equational reasoning. blah the_v_in_scope blah where (the_v_in_scope:_) = [ v | (n,v) - env, n==target ] This piece of code isn't. Strange. It's semantically the same, isn't it? Indeed, the definition of head gets you to it. If you used head then you could trivially inline the_v_in_scope, this way is a lot harder. I don't follow that at all. I don't do inlining, the compiler does. Or are you talking about the inlining that was originally there and my version explicitly removed? You might spot a pointfree pattern and lift it up. You might move code around more freely. Lots of patterns like this breaks the equational reasoning in the style that most people are used to. To convince me of that, you'd have to convince me that (head []) doesn't break the equational reasoning. and it doesn't seem /that/ great an imposition. I disagree, this is a massive imposition, and requires lots of refactoring, lots is in the eye of the beholder. You only have to do this where you would have used head -- and if you can already /prove/ that head won't fail, there's no reason to replace it. So it's only necessary in cases where the proof is absent. and is just a little bit ugly. Sure, I don't dispute that. I was merely suggesting that one can already do this for the uncertain cases, rather than have to invoke a whole other set of new machinery just to get a line number in the error message. Your headNote is a good approach, but it strikes me that it's a bit redundant. Instead of “headNote foo” just use “headDef (error foo)”. It's a wee bit longer, but having the “error” out there in the open seems more honest somehow, and there would be fewer function names to remember. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Debugging partial functions by the rules
Robert Dockins [EMAIL PROTECTED] writes: On Nov 15, 2006, at 9:48 AM, Jón Fairbairn wrote: But instead of “blah (head [ v | (n,v) - env, n==target ]) blah”, you could write blah the_v_in_scope blah where (the_v_in_scope:_) = [ v | (n,v) - env, n==target ] Or how about ?? lookupVarible target env = case [ v | (n,v) - env, n==target ] of (x:_) - x _ - assert False $ BUG: Unexpected variable out of scope ++ (show target)++ in environment ++(show env) ... lookupVariable target env It seems to me that every possible use of a partial function has some (possibly imagined) program invariant that prevents it from failing. Otherwise it is downright wrong. 'head', 'fromJust' and friends don't do anything to put that invariant in the program text. Hear hear. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Generalizing zip
Jason Dagit [EMAIL PROTECTED] writes: Well, this is basically just a zip with a special base case. But you can't just write it with zipWith because zipWith stops when it exausts either list. How about we define zipWith'' like this: zipWith'' _ [] _ l _ = [l] zipWith'' _ _ [] _ r = [r] zipWith'' f (x:xs) (y:ys) l r = f x y : zipWith'' f xs ys l r Then we can write: isPrefixOf xs ys = and (zipWith'' (==) xs ys True False) I wonder if there is mileage to be had from persuing something like this, rather different (off top of head, very provisional, EOE c) approach: extend_infinitely l = map Just l ++ repeat Nothing promote1 rel (Just a) b = rel a b promote1 rel Nothing b = False is_pfx_of l1 l2 = and (zipWith (promote1 (==)) (extend_infinitely l2) l1) ? For at least the few minutes I've thought about it, it seems like promote and extend_infinitely might be more generally userful. I've probably missed something better, too. A point free reduction might look like the following and probably isn't worth it: isPrefixOf = (and .) . flip flip False . flip flip True . zipWith'' (==) probably? -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Generalizing zip
Jón Fairbairn [EMAIL PROTECTED] writes: Jason Dagit [EMAIL PROTECTED] writes: Well, this is basically just a zip with a special base case. But you [...] I wonder if there is mileage to be had from persuing something like this, rather different (off top of head, very provisional, EOE c) approach: extend_infinitely l = map Just l ++ repeat Nothing promote1 rel (Just a) b = rel a b promote1 rel Nothing b = False is_pfx_of l1 l2 = and (zipWith (promote1 (==)) (extend_infinitely l2) l1) or, possibly better extend_infinitely l = map Just l ++ repeat Nothing is_pfx_of l1 l2 = and (zipWith (==) (extend_infinitely l2) (map Just l1)) -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Friday Afternoon Play: The Burrows Wheeler Transformation
So, it's Friday afternoon (well, here anyway), and presumably everyone is thinking of leaving for the weekend. Is anyone interested in playing a little game? I'm going to make the first move, and then just wait and see if anyone makes the next. I'm certainly not promising to make any further moves myself, but I'm not promising I won't, either. Below you'll see a naïve implementation of the Burrows Wheeler transformation and its inverse. That's my move. (And don't complain too much about style and such -- I'm half asleep.) Further moves are made by transforming the programme so that it becomes more efficient. The first target is not raw speed, but to adjust it until the computational complexity gets to be what it should be. I'm hoping for elegant moves here. After that, folk might start replacing the lists with more efficient datastructures and so on, but still /elegantly/. The object of the game isn't ultimate speed -- I've no particular wish to see a Haskell version that's as fast as a good C version, especially not if it ends up /looking/ like a C version. Really the objective is to think about Haskell programming -- and probably come up with some observations such as there really ought to be a class of indexable structures, so that we don't have to change (!!) to (!) all over the place. And to have fun, anyhow... * * * Demonstration of the principle of the Burrows Wheeler transform. The implementations are simplistic (and have worse complexity than is possible). module Burrows_Wheeler_Transform where import List This is surely the wrong module to have to find () from: import Data.Graph.Inductive.Query.Monad(()) The forward transformation. Input a list, output the transformed list and possibly an int (Nothing if there were no elements in the input -- perhaps the result type should be Maybe (NonEmptyList t,Int)) slow_bwt:: Ord t = [t] - ([t], Maybe Int) This version works by computing a list of all the rotations of the input and sorting it. The transformation is then the last element of each line of the sorted rotations. Tag the data with an index so that it's possible to find where the original form of the unput ends up after sorting. This is essentially the specification of the transform coded up directly. slow_bwt l = (map fst tagged_bwt, index_of_original) where tagged_bwt = map (lastid) $ sort $ rotations l`zip`[0..] index_of_original = findIndex ((==0).snd) tagged_bwt that looks like worst case n²×log n to me (where n is the length of the string): if every element is the same, the n×log n comparisons the sort does will each look at every element, and that's really more than is necessary. The inverse transform. We should have that @ slow_inv_bwt . slow_bwt == id @ Observe that sorting the input gives the first column of the sorted rotations (and the input is the last). So after one sort we have X... c Y... b Z... a . .. . .. . .. Since they are rotations, rotating each row of this gives pairs that belong to the original list: cX ... by ... aZ ... . . . . . . sorting these gives us the first two columns of the sorted rotations, and again we already know the last column, which can be rotated into the first and so on. slow_inv_bwt ([],_) = [] slow_inv_bwt (l,Just index_of_original) = iterate catsort (replicate len []) After (length input) iterations we have the original sorted rotations, !! len and we have the index of where the untransformed string is, so we can just pick it back out. !! index_of_original where catsort s = sort $ map (uncurry (:)) $ l `zip`s len = length l This version does rather fewer sorts: mark2_inv_bwt ([],_) = [] mark2_inv_bwt (l,Just n) = (transpose $ take (length l) $ iterate (permuteWith perm) l)!!(perm!!n) where perm = map snd $ sort $ l `zip` [0..] Should I simply have left it out and hoped that it would turn up after a few moves? I'm not going to explain it, anyway. rotations l = init $ zipWith (++) (tails l) (inits l) permuteWith ns l = map (l!!) ns -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Would someone explain this code to me?
Justin Bailey [EMAIL PROTECTED] writes: I'm reading Chris Okasaki's Purely Functional Data Structures, and some of his Haskell is confusing me. He defines the type Color and RedBlackSet as: data Color = R | B data RedBlackSet a = E | T Color (RedBlackSet a) a (RedBlackSet a) and then later he defines a function insertSet: insertSet x s = T B a y b where ins E = T R E x E ... T _ a y b = ins s What I don't understand is his use of the T constructor, both at insertSet x s = T B a y b Here it creates a new RedBlackSet and in the where statement: T _ a y b = ins s Here it's a pattern match. So if ins s returns (T x a' y' b'), then a = a'; y = y'; b = b' are used in the expresion covered by the where clause. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Cannot understand liftM2
Nicola Paolucci [EMAIL PROTECTED] writes: Hi All, I'm loving learning Haskell quite a bit. It is stretching my brain but in a delightfull way. I've googled, I've hoogled but I haven't found a clear explanation for what exactly liftM2 does in the context below. Using the cool lambdabot pointless utility I found out that: \x - snd(x) - fst(x) is the same as: liftM2 (-) snd fst I like the elegance of this but I cannot reconcile it with its type. I can't understand it. I check the signature of liftM2 and I get: Prelude :t liftM2 Prelude liftM2 :: (Monad m) = (a1 - a2 - r) - m a1 - m a2 - m r Can someone help me understand what's happening here ? What does a Monad have to do with a simple subtraction ? What is actually the m of my example ? I am sure if I get this I'll be another step closer to illumination ... Does typing :t liftM2 (-) snd into ghc enlighten you at all? -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Aim Of Haskell
Neil Mitchell [EMAIL PROTECTED] writes: Talking to professional programmers, if I tell anyone I program in Haskell they nearly always say oh, Pascal, that's cool. You need to say askell... No one knows what functional programming is, Scheme/Lisp are the closest. Maybe we should try and hijack the phrase functional programming I think we should call it Abstraction Oriented Programming. It's got the oriented buzzword in it, and we don't need to tell folk that abstraction means more than one thing to us until we're sure they're OK. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Idiomatic Haskell equivalent of keyword arguments to functions
Neil Mitchell [EMAIL PROTECTED] writes: To make things concrete, the example I'm really thinking of is a send an email function, which would take a subject, a body, a list of recipients, optional lists of cc and bcc recipients, an optional mailserver (default localhost), an optional port (default 25), and possibly optional authentication details. Records are your friend. data Email = Email {subject :: String, body :: String, to :: [Address], cc = [Address], bcc = [Address], mailserver :: String, port :: Int} defaultEmail = Email{subject = No subject, body = , to = [], cc = [], bcc = [], mailserver = localhost, port = 25} The user can then go: sendEmail defaultEmail{subject=Subject here, body = body here, to = [haskell-cafe], mailserver = server.haskell.org} Now things which are't specified (port) keep their default value. If you do this for more than one function (and consequently more than one datatype) there's a case for a class -- something like: class Defaultable t where defaults:: t instance Defaultable Email where defaults = Email{subject = No subject, body = , to = [], cc = [], bcc = [], mailserver = localhost, port = 25} which would save having a defaultFoo for every Foo (at the possible expense of occasional explicit types). -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: basic field questions
Ketil Malde [EMAIL PROTECTED] writes: jamin1001 wrote: What if I want to do something like data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int} data Properties = Props { pos, color :: Int } data Chair = Chair Props data Table = Table Props or: data Chair = Chair Int Int data Table = Table Int Int class Furniture a where pos :: a - Int color :: a - Int instance Furniture Chair where pos (Chair x _) = x color (Chair _ c) = c I'm not sure I follow what's really wanted here. Whats wrong with this: data Colour = Black | Brown deriving (Enum, Show) data Furniture = Table {colour:: Colour, weight:: Double, height:: Double} | Chair {colour:: Colour, weight:: Double, squishiness:: Double} deriving Show and then... ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.4.2, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \/\/ /_/\/|_| Type :? for help. Loading package base-1.0 ... linking ... done. Prelude :l /tmp/foo.lhs Compiling Foo ( /tmp/foo.lhs, interpreted ) Ok, modules loaded: Foo. *Foo colour $ Table {colour = Black, weight=1, height= 2} Black *Foo colour $ Chair {colour = Brown, weight = 1, squishiness=100} Brown *Foo The requirement is that all the colour fields have the same type. The record system is somewhat wartish, Sure, but it's not obvious to me that we're looking at one of the warts here, unless the problem is that my Furniture above isn't extensible in the appropriate sense or someone wants the different coulour fields to have different types (confusing, surely?). -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: How did you stumble on Haskell?
Lennart Augustsson [EMAIL PROTECTED] writes: On Jan 29, 2007, at 03:01 , Alexy Khrabrov wrote: How do people stumble on Haskell? Well, I didn't really stumble on it. I was at the 1987 meeting when we decided to define Haskell. But I stumbled on functional programming in the first place. I had to learn it because it was part of a course in denotational semantics. OK, if we old lags are going to give our excuses... I was a member of an undergraduate society in Cambridge called the Processor Group. I went along to a talk that Arthur Norman gave to them (must have been 1980±1?) in which he described (S, K, I) combinators and his plans for the SKI Machine (SKIM). The fact that S and K on their own gave a complete computational basis was the most exciting piece of computer science I'd encountered at that point and I just had to follow it up. So some years later I ended up at that same 1987 meeting. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: How did you stumble on Haskell?
Paul Johnson [EMAIL PROTECTED] writes: I'd read Eric Raymond's piece about being a hacker, where he said to learn Lisp for the side effects. Much better to learn Haskell for the side effects! ;-) -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: speeding up fibonacci with memoizing
Thomas Hartman [EMAIL PROTECTED] writes: - I just thought this was interesting, so I would share it. - -- versus, try memoized_fibs !! 1 - memoized_fibs = map memoized_fib [1..] - memoized_fib = ((map fib' [0 ..]) !!) - where - fib' 0 = 0 - fib' 1 = 1 - fib' n = memoized_fib (n - 1) + memoized_fib (n - 2) I can't let this thread go by without commenting that you can do something a bit more general by providing a memoising fixpoint operator that you can reuse for your other awkward recursive functions: module MemoFib where The unexciting version naive_fib 0 = 1 naive_fib 1 = 1 naive_fib n = naive_fib (n-1) + naive_fib (n-2) The memoised version using a memoising fixpoint operator fibonacci = memoFix fib where fib fib 0 = 1 fib fib 1 = 1 fib fib n = fib (n-1) + fib (n-2) I suppose if you want to put it in a library, you should just put fib in, and allow the user to call memoFix fib to make a new version when necessary? A memoising fixpoint operator. It works by putting the result of the first call of the function for each natural number into a data structure and using that value for subsequent calls ;-) memoFix f = mf where memo = fmap (f mf) (naturals 1 0) mf = (memo !!!) A data structure with a node corresponding to each natural number to use as a memo. data NaturalTree a = Node a (NaturalTree a) (NaturalTree a) Map the nodes to the naturals in this order: 0 1 2 3 5 4 6 7 ... Look up the node for a particular number Node a tl tr !!! 0 = a Node a tl tr !!! n | odd n = tl !!! top | otherwise = tr !!! (top-1) where top = n `div` 2 We surely want to ba able to map on these things... instance Functor NaturalTree where fmap f (Node a tl tr) = Node (f a) (fmap f tl) (fmap f tr) If only so that we can write cute, but inefficient things like the below, which is just a NaturalTree such that naturals!!!n == n: naturals = Node 0 (fmap ((+1).(*2)) naturals) (fmap ((*2).(+1)) naturals) The following is probably more efficient (and, having arguments won't hang around at top level, I think) -- have I put more $!s than necessary? naturals r n = Node n ((naturals $! r2) $! (n+r)) ((naturals $! r2) $! (n+r2)) where r2 = 2*r Of course, if you want to take advantage of the pseudo O(n) lookup time of arrays, you could use a NaturalTree of arrays of some fixed size -- but arrays are O(log n) really... -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: what I learnt from my first serious haskell programm
Fawzi Mohamed [EMAIL PROTECTED] writes: Vectors don't act like numbers, a vector space is not a field, even if they have some common operations. That's a long-standing flaw in the design of numeric classes. It's not a problem with typeclasses per se. I find it misleading to define something a number when it does not satisfy all the properties of numbers. Justifiably so. But if you had a class Additive, would you be unhappy about defining (+) on non-numbers? The numerical prelude might fix this, but still I think that class and overloading should be distinct concepts. I think the problem here is that you are using the word class to mean something different from Haskell classes. Haskell typeclasses /are/ overloading, and that's what I understand them as. They were originally introduced as a solution to the question of how to handle equality so that one didn't have to use different names for the same concept on different types. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-13) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: toClockTime
Jeremy Shaw [EMAIL PROTECTED] writes: Try using Data.Time instead -- it was written by a self-professed time nerd, and probably works correctly. It was added in GHC 6.6 and largely supercedes System.Time. Curiously, Hoogle doesn't seem to have it indexed yet -- I was looking for it just the other day and didn't find it. I'm glad it's there in 6.6 -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-13) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Writing guards shorthand
Joel Reymont [EMAIL PROTECTED] writes: Support I want to infer the type given an Op that looks like this (incomplete): data Op = Minus | Plus | Mul | LT | GT Is there a shorthand way of bunching Minus, Plus and Mul in a function guard since they all result in TyNum whereas the rest in TyBool? I really don't want several function clauses and neither do I want separate guards for every constructor. Is there some reason why you don't want data Op = Aop Aop | Bop Bop data Aop = Minus | Plus | Mul data Bop = LT | GT or similar? I would agree that it's a shame one cannot just write data Op = Aop (Minus | Plus | Mul) | Bop (LT | GT) or even, given a somewhat different type system, data Op = Aop | Bop where Aop = Minus | Plus | Mul Bop = LT | GT but it would seem reasonable to reflect the different types of the Ops in different types in their representations. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: The Functional Pearls
[EMAIL PROTECTED] (Donald Bruce Stewart) writes: I've created a wiki page collecting the 'functional pearl' papers that have appeared in JFP and ICFP and other places over the last 20 odd years. http://haskell.org/haskellwiki/Research_papers/Functional_pearls Lots of lovely functional programs there. There's also a list on that page of pearls that don't appear to be online. If you know where they live, please add the links! The ones that appear in JFP are on line... in some sense... it's just they want money for looking at them. I don't suppose we could somehow persuade CUP to make them freely accessible after a year or two? -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: global variables
Eric [EMAIL PROTECTED] writes: H|i, Does anyone know of a simple and straightforward way to use global variables in Haskell? No, no-one does. Global variables are neither simple nor straightforward. :-P In addition to what others have said (assuming you don't just mean providing a name for a constant¹), to avoid the problems caused by global variables is one of the reasons for using a functional language. [1] as in e = exp 1 -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe