foldM vs. foldL and foldR
Please, could anybody explain me what the rationale behind the current foldM in Monad? At least of the IO monad, it seems important to have a left associative fold instead of the right associative foldM. Adding to my confusion, it seems that earlier in time, there was indeed two monad fold's instead of just one. Confused, Tommy
Haskell 1.3?
Quoting from "Introducing Haskell 1.3" (http://www.cs.yale.edu/ HTML/YALE/CS/haskell/haskell13.html): "The final version of the Haskell 1.3 is expected to be complete in January, 1996." Does anyone know what happens? Regards, Tommy -- "When privacy is outlawed, only outlaws will have privacy." -- Phil Zimmerman
pattern guards and guarded patterns
I can see the arguments for the pattern guard extension and the syntax seem reasonable. I also agree with Chris on the shortcomings of if-then-else. (I have disliked it in any language where I've seen it, and it "feels" un-Haskell-like to me.) On the other hand, the suggested case | ... -> ... syntax seems confusing (overloads `case') and redundant (we don't need a SML-like `|', we have layout rules). Although its origin is the case expression, the special syntax is a witness to the fact that it is different. Something like cond x == y -> same x x == y*2 -> haly x . otherwise -> default x would be much easier on my stomach. My only worry is that Haskell (if not already) is turning into the C++ of functional languages, ie. feature upon feature. Haskell is already quite a mouthfull to learn. /Tommy
Evaluating Haskell
David Wilczynski raises some very important and interesting questions about Haskell from a "Real World" point of view. I would very much like to see this kind of discussions, which I feel are essential if Haskell is ever to move out of the laboratories. Please do *not* move this discussion into private email or phone. I'll just comment on one small item: > Is there a strategy in which an > engineer can learn a useful subset of Haskell, and grow into it as need be? > I am unconvinced by arguments such as "this perfectly ordinary Yale > graduate student learned Haskell in just 8 days." I think it was about correct for me, although understanding type classes well enough to create my own (as opposed to just using them) too a lot longer. I generally "feel" Haskell as one of the simplest languages I know(!), in the sense that things are natural, logical, general, and without unpleasant surprises. Of course, this is just relatively to the many other languages I know (not least Java). > 4) Concurrency -- I saw that one of the compilers supported Concurrent > Haskell. I don't recall seeing any mention of it in any of the material I > have. Have I missed it? No, concurrency is not part of the standard language, but it would sure be nice if it was (hint hint). I look forward to follow the discussion, Tommy
Punning: Don't fix what ain't broken.
John Hughes wrote on the Std Haskell board: > `Punning' can be used in three places in Haskell. Suppose a record > type is defined by > > data R = R{x :: Int} > > Then > * R{x} constructs a record, and is equivalent to R{x=x} > * r{x} updates the x field of record r, and is equivalent to r{x=x} > * R{x} can be used as a pattern; its meaning is not defined by the > report, but is presumably supposed to be the same as R{x=x} > > I've used this. It's convenient, but I had a bad taste in my mouth > afterwards. I support removing all forms of punning from the > language. But this would, of course, break existing programs. I want > to do it anyway. Note that the puns become syntactically incorrect > in every case, so broken programs can be mended just by correcting > the syntax errors. I'm surprised and disappointed with the Standard Haskell effort on punning. A grand total of two messages but absolutely no discussion and *pop* there it went down the pipe. Yes it convenient, and sometimes even very convenient. I can't see the value of arguments like "bad taste in the mouth". Why was it introduced in the first place? Are there any *known* examples where this feature has caused problems? As John notices, the punning form do not overlap syntactically with anything, so you can't used them by accident. Instead of junking it, I would rather have seen the pattern matching punning syntax (R{x}) become official, as this is the most useful of the three punning. /Tommy
Re: Punning: Don't fix what ain't broken.
Koen Claessen: > This brings us to another issue. Doesn't the following definition look > a bit awkward? > > R{ x = x } Definitely wierd. The left and right-hand side denotes two different things, which AFAIK is the only place where `=' behaves like this. Wouldn't `<-' have been a better choice? `<-' bindings are never recursive, thus `R{ x <- x } is less surprising, as the two x's can't be the same. It would be worth taking into account if completely revising the record handling of Haskell, but in itself it's too small a gain to be worthwhile. My humble opinion, Tommy
the overloading of ==
Victor M. Gulias wrote/a ecrit/skrev: > As a naive implementation of "all" and "any", one of my students coped with > these definitions: > > any' p xs = [x | x <- xs, p x] /= [] > all' p xs = [x | x <- xs, p x] == xs I used to be in favor of the monadic overloading of list operations, but this example is really shocking. I note as well that the errors messages from both Hugs and GHC leaves a lot to be desired. /Tommy
FP Naming/Directory Service
S. Alexander Jacobson wrote/a ecrit/skrev: > I just started playing with Haskell for CGI applications. > I would like to try writing a more serious CGI app, but > missing infrastructure makes it more difficult than conventional > approaches. On a general note, I too try employ Haskell for more and more common- day tasks (eg replacing a great number of shell/Perl hacks) and almost daily face the lack of support, mostly in the form of missing libraries. I think there are two major causes to this effect: one is the high emphasize on theoretical aspects of the language and a disproportional low effort on plain practial aspects. Contrast this with the development of languages like Erlang and Java. In the latter case the language was carved in stone long time ago (*) and the effort concentrated on producing a mind-bogling large library, covering all sorts of applications. Another causes is the simple observation that Java users largely outnumber Haskell users. The only option we have (IMHO) is to ease and streamline the process of introducing new libraries and write and make available good libraries as the needs are encountered. In this respect, GreenCard constitutes a key element. (*) I'm not claiming that this is a good idea, even less that they where successful. > In decreasing order of preference, is there an available > implementation of: > * an equivalent to Java's Naming and Directory Services interface > * an LDAP client for some particular LDAP server > * an XML editor > * a generic ODBC/JDBC database client > * an interface to berkeleyDB (or some persistent hashtable > implementation) > > I suppose that I could have Haskell talk to Jacl to access the Java > implementations of these capabilities, but this seems like a hack. > > Any pointers? I don't the first three at all, so I can't comment on them. AFAIK, writing a library with more or less the same functionality as ODBC/JDBC should be perfectly doable. As for the latter, I imagine that something very useful could be built in combination with the Binary library from York (a should-be standard library, IMHO). /Tommy
Phil's Pretty Printing Library
In an attempt to gather experience with Philip Wadlers pretty printing combinators, I converted a semi big pretty printer to his pretty printing. My initial experiences are positive: while Phil's combinators are clearly less expressive, they were expressive enough (at least with the improvements below) and the results was subjectly clearer. For the utility of others which might wish to experiment I include my library, apologizing up front from the lack of clean-up, documentation, and optimization. On an unrelated note, I like to add that I consider it a feature, not a bug, that combinators build a Doc structure, as this enables a later unforseen interpretation of the document. Such an interpretation could be for proportional fonts, colors, etc. /Tommy --- Philip Wadlers Simplified Pretty Printing Library Hacked somewhat to pieces by Tommy Thorn, 26/3-1998 Major changes: - <+> and $$ has nil (empty) as unit. - bline is a blind line that disappears when flattened > module WadlersPretty where > infixr 5 :<|> > infixr 6 :<> > infixr 6 <>, <+> > infixr 5 , $$ > data Doc= Nil > | Doc :<> Doc > | Nest Int Doc > | Text String > | Line > | BLine -- blind line > | Doc :<|> Doc > > data DOC= NIL > | String `TEXT` DOC > | Int `LINE` DOC > > > nil = Nil Maintain canonical form > Nil <> y= y > x <> Nil = x > x <> y = x :<> y > nest k Nil = Nil > nest k x= Nest k x `text ""' is not the same as nil > text= Text > line= Line > bline = BLine > group x = flatten x :<|> x > > flatten Nil = Nil > flatten (x :<> y) = flatten x :<> flatten y > flatten (Nest i x) = Nest i (flatten x) > flatten (Text s)= Text s > flatten Line= Text " " > flatten BLine = Nil > flatten (x :<|> y) = flatten x > > layout NIL = "" > layout (s `TEXT` x) = s ++ layout x > layout (i `LINE` x) = '\n' : copy i ' ' ++ layout x > > copy i x= [ x | _ <- [1..i] ] > > best w k x = be w k [(0,x)] > > be w k [] = NIL > be w k ((i,Nil):z) = be w k z > be w k ((i,x :<> y):z) = be w k ((i,x):(i,y):z) > be w k ((i,Nest j x):z) = be w k ((i+j,x):z) > be w k ((i,Text s):z) = s `TEXT` be w (k+length s) z > be w k ((i,Line):z) = i `LINE` be w i z > be w k ((i,BLine):z)= i `LINE` be w i z > be w k ((i,x :<|> y):z) = better w k (be w k ((i,x):z)) (be w k ((i,y):z)) > > better w k x y = if fits (w-k) x then x else y > > fits w x | w < 0= False > fits w NIL = True > fits w (s `TEXT` x) = fits (w - length s) x > fits w (i `LINE` x) = True A Pretty Class > class Pretty a where pretty :: a -> Doc > instance Pretty Char where pretty c = text [c] > instance Pretty Intwhere pretty n = text (show n) Utilities > Nil <+> y= y > x <+> Nil = x > x <+> y= x <> space <> y > Nil $$ x= x > x $$ Nil = x > x $$ y= x <> line <> y > xy= x <> line <> y -- force a newline > punctuate sep [] = nil > punctuate sep [x]= x > punctuate sep (x:xs) = x <> sep <> punctuate sep xs > vcat = punctuate line > sep x= group (vcat x) > parens x = text "(" <> x <> text ")" > brackets x = text "[" <> x <> text "]" > braces x = text "{" <> x <> text "}" > empty= nil > space= text " " > period = text "." > comma= text "," > semi = text ";" > colon= text ":" > int :: Int -> Doc > int n = text (show n) > char :: Char -> Doc > char n = text [n] > instance Show Doc where > showsPrec _ x = showString (layout (best 79 0 x)) > putDoc :: Doc -> IO () > putDoc x = putStr (layout (best 79 0 x))
Re: Phil's Pretty Printing Library
> Incidentally, the above def of `sep' doesn't match Hughes' in an important > way. Consider: Aiee, I knew this was gonna backfire. No, my `sep' does not (and wasn't intended to) have exactly the same semantics as Hughes' `sep'. Also, please understand that Phil never proposed such a `sep'. Likewise with the other combinators with the same name as Hughes'. The purpose of using the same names was just to ease the transition, not to eliminate it. Apologies to everyone for not making this clear. /Tommy
Keep it up! [Re: Where is Haskore discussed?]
Hi there, Just a my "deux centimes" to say that I'm happy with "application" oriented discussion on the Haskell list. In fact, I'd be happy to see more "applications" discussed, like CGI, Fran, Happy, ... /Tommy
Re: FW: Exceptions are too return values!
Thats a wonderful idea. With that it will be so much easier to write robust code without bloating the code with error checks. I've always been annoyed that I couldn't trap arbitrary errors, say to close down the application cleanly. Now, we only need extendible data types, and then we have an (almost) ML-like exception system :) /Tommy Simon L Peyton Jones wrote/a ecrit/skrev: > > Alastair Reid has been very quiet, so I'll pipe up for him. > > Here's a reasonable design for exceptions in Haskell: > > * A value of Haskell type T can be > EITHER one of the values we know and love > (bottom, or constructor, or function, > depending on T), > > OR it can be a set of exceptional values. > > * raise :: String -> a > (raise s) returns a single exceptional value, named by string s > > * All strict operations (case, +, etc) return the union of > the exceptional values returned by their strict arguments > For example, if both arguments to "+" return an exceptional value > then "+" returns both. Similarly, any strict context. > > * handle :: (String -> IO a) -> IO a -> IO a > (handle h a) tries to perform the action a. > If doing so delivers a set of exceptional values then > apply the exception handler h to the string that names > one of them. It is not defined which of the exceptional > values is picked. > > > The neat thing about this is that the exceptions can > be *raised* in arbitrary purely functional code, without > violating referential transparency. The question of > which exception is chosen is done in the IO monad, where > of course it is allowed to be non-deterministic. > The implementation does not keep sets of exceptional values, > of course. It simply propagates the first one it trips > over to the nearest enclosing handler. > > (It is likely that successive runs will actually give > the same behaviour, but recompiling the program with > (say) different optimisation levels might change the order > of evaluation, and hence change which exception is tripped > over first.) > > We're implementing an experimental version of this > in GHC, integrated with the IO monad exceptions, so that > > handle :: (IOError -> IO a) -> IO a -> IO a > > and we add an extra constructor (UserError String) to the > IOError type for exceptions raised by raise. > > Calls to "error" also show up as an exceptional value, of > course. > > One merit of the system is that it chops out a tremendous > number of run-time error checks in the IO monad, since > we are now free to implement the mechanism with standard > stack-unwinding techniques. Result: much better I/O performance. > > > I'd be interested to know what people think of this. > > Simon
GHC import chasing [Was: GHC/Hugs Status]
Alastair Reid wrote/a ecrit/skrev: > > * import-chasing as part of the spec > > This is an environment feature not a language feature. > > What does it mean for GHC? > Are you wanting to do away with Makefiles? > Makefiles can do an awful lot more than import chasing can > and GNU makefiles are very, very short in the normal case. I use a lot of Makefiles, but why must we use ugly tools with beatiful languages? They are especially bad for a novice, just trying to gain a little more speed on his Hugs program. What I'd really like to do is just: ``ghc Main.hs'', and obtain a Main executable. For the more advance user (using Green-Card, Happy, and whatnot) there should always be the brainless "C-style" way. I fail to see why GHC must be so difficult to use for multi file programs(*). /Tommy (*): I'm perfectly willing to accept that I'm a clueless newbie, but even after having read the manual and studied the code, I wasn't able to get a working Makefile. Is it doable in a few easy steps? Mind you, that ``ghc -M'' did not cut it: the default rules weren't specified.
Plea for Change #1: Why, O why, `Main'?
Jens' question gave my a perfect opportunity to open my a pet peeve of mine: the ditatorship of `Main'. In Haskell, the `main' function must reside in the `Main' module. Add to this that the `Main' module must reside in a `Main' file and you have an unfortunate consequence that you can only have one `Main' function in each directory. This in turn means that to have, for example several variants of a program, you *must* defer to either messing with a preprocessor or dealing with multi-directory compilation, not a pretty sight in either case and especially daunting to a beginner. In this Haskell is in contrast to most other popular programming language. The alternative seems quite straightforward and there are no technical difficulties: 1) Accept the `main' function can be put in any module, and/or 2) Introduce a nothing of "anonymous" modules, of which the file name can be anything. I'd prefer 1) alone. /Tommy
Plea for Change #2: Tools
I have another pet peeve: ease of use of tools. The Haskell standard (intentionally?) leaves the interface to tools an implementors question. Unfortunate, IMHO, every Haskell compiler I've tried (GHC, NHC, HBC) have just had plain horrible interfaces. Interpreters are inherently a different story, but Hugs at least is a lot more friendly. Even when taking the simple example from my previous^2 post ghc -c Add.hs ghc -c Main.hs ghc -o Main Main.o Add.o we notice that it takes three commands, in the right order, each with a non optional flag. There is nothing present here that couldn't be deducted directly from the contents of `Main.hs', thus a simple `ghc' (or `ghc Main' assuming my first plea) command should have sufficed. Now granted the three commands above isn't exactly rocket science and anyone with a little exposure to `C' (God forbid) would immediately feel at home. Only, this naive interface only brings the deficiencies of C to the complexity of a type checked module based language. Maintaining dependencies with makefiles is both hairy and error prone. There exists scripts like `ghcmake', but that's only patching a rotten foundation and cracks are quick to surface (try anything non trivial, like using multiple directories). I'm not targeting `ghc' in particular, but I do feel that for a programming language that stresses cleaness, the tools should reflect the same: simple things should be simple to do. The report should state the least common denominator interface to command line tools, at least up to relatively simple tasks like compiling a multi-module program (spanning several directories). How about `haskell2 [-I ] '? /Tommy
Main.main [Was: question to GHC 4.02]
Dear Jens, the problem is quite simple, but alas, the error message leaves much to be disired: standalone Haskell program must contain a `main' function in the `Main' module (thus the missing Main_main_closure reference). Furthermore, this `main' function must have the type signature `IO ()' (or was that finally changed to `IO a'?). In essence, you have just given a function (`add'), but not specified how your program should interact with the world. To do this you could add a module like: module Main where import Add main = print (add 42 1729) and compile with ghc -c Add.hs (file and module name must be identical) ghc -c Main.hs ghc -o Main Main.o Add.o Best regards, Tommy [EMAIL PROTECTED] wrote/a ecrit/skrev: > Dear Sir or Madam > > I have written this small simple program > > module Add where > add :: Int -> Int -> Int > addx1 x2 x1 + x2 > > I have create an object file with the command % ghc -c additon.hs > Now I will create an executable file. > What I have to do? > > The command % ghc -o addition addition.o give me following failure message: > > /usr/lib/ghc-4.02/libHS.a(PrelMain__8.0)(.text+0x2a) > undefined reference to 'Main_main_closure' > /usr/lib/ghc-4.02/libHS.a(PrelMain__8.0)(.data+0xc) > undefined reference to 'Main_main_closure' > > If you can help me, please contact me under: > > [EMAIL PROTECTED] > > I use a Red Hat 5.1 system and GHC 4.02 . > > Yours sincerely > > Jens Fiedler
A datatype for the text editor buffer?
Peter Hancock wrote/a ecrit/skrev: > I don't think its crazy. I thought that one could start with > something simple, like a "before" list and an "after list". Indeed. When I was getting into Haskell, I hacked the ansi.hs example from the Hugs distribution to add editing. Parts of the function actually became simpler this way. Regards, Tommy readAt:: Pos -> -- Start coordinates Int -> -- Maximum input length (String -> Interact) -> -- How to use entered string Interact readAt (x,y) l use = writeAt (x,y) (copy l '_') (moveTo (x,y) (loop "" "")) where loop rh t -- Inv: s == (reverse rh)++t = readChar (return rh t) (\c -> case c of '\BS' -> delete1 rh t '\DEL'-> delete1 rh t '\n' -> return rh t '\002'-> backwards rh t '\006'-> forwards rh t c | (length (rh++t)) < l && ' ' <= c -> writeChar c (writeLoop (c:rh) t) | otherwise -> ringBell (loop rh t)) backwards [] t = loop [] t backwards (c:rh) t = writeChar '\b' (loop rh (c:t)) forwards rh[] = loop rh [] forwards rh (c:t) = writeChar c (loop (c:rh) t) delete1 [] t = ringBell (loop [] t) delete1 (c:rh) t = writeChar '\b' (writeLoop rh t) writeLoop rh t = writeString (t++"_"++(copy ((length t)+1) '\b')) (loop rh t) return rh t = use ((reverse rh)++t)
Stylistic question about Haskell optional arguments
Andy Gill wrote/a ecrit/skrev: > I've got a stylistic question about Haskell. > What's the best way to add optional arguments to a > embedded DSL? > > For example, say I've got an library of HTML combinators. > To represent > > This is a Header > > you might write > > h1 (stringToHtml "This is a Header") > > The types of the functions are > > h1 :: Html -> Html > stringToHtml :: String -> Html Please make that an instance operator, such that you don't have to litter the name space, eg. h1 :: HTML -> HTML class HTMLable a where html :: a -> HTML > Looks OK, but what about if you want this header > right aligned? I can see three ways. > (2) Combinators that take arguments have different names. > So you might have > > h1 :: Html -> Html > h1' :: [HtmlAttr] -> Html -> Html IIRC this is what TkGofer used. Works nice in practice and is _simple_! Say, are you making a better version of LibCGI? We could use a maintained, unified, and more complete library. Regards, Tommy
Re: Haskell HTTP lib?
Sven Panne wrote/a ecrit/skrev: > William Lee Irwin III wrote: > > Personally, I'd like to see some equivalent of the C system call > > select(2) in GHC's socket library; [...] > > About a year ago this has been discussed, but the implementation has > somehow vanished from GHC's sources. Strange... > >http://www.dcs.gla.ac.uk/mail-www/glasgow-haskell-bugs/msg01147.html I'm happy to see my old plea reanimated. It interesting to note that now, a year later, the situation hasn't improved much. It seems most everybody agrees that lack of access to system libraries makes it impossible to employ Haskell for certain tasks. The various FFIs promises to help out here, but correct me if I'm wrong, but it seems that _none_ of the existing FFIs would help here, as support for select depends on the implemention of Haskell primitives, such as Handle. Regads, Tommy
Mixing fruits [Was: Clean and Haskell]
I makes very little sense to compare GCC (C++) with GHC (Haskell) inspite of the sneaky names. 1) While no C++ expert, I'd conjecture that compiling C++ is roughly five times harder than C, due to C++ being a much larger language with _many many_ ugly corners. The difficulty in compiling Haskell is not exactly comparable, as the language it much more advanced, but also far more streamlined. Haskell however, has also grown to be a fairly large language. 2) Whereas for the speed of compilers there's little in C++ that should slow down a _non_ optimizing compiler (well...). C++ evolved from C and C++ compilers evolved from C compilers. C was designed such that you could compilable it on the machines available at the time (that is, less than 64k). Haskell, however, was designed in modern time and require much more work of the compiler (even a _non_ optimizing compiler) in order to save the work of the programmer. As a consequence of the language there is less room and need for optimization when compiling C++, and the optimization rarely improves the result in a spectacular way. With Haskell, the situation is quite different. There can be a world of difference between the performance of a naive Haskell compiler and a sophisticated one and there is likely to be a correlation with the compile time. 3) Compiling C and C++ is relatively well understood and GCC is a production level compiler. Compiling Haskell is still the basis of active (? :-) research and GHC is a research project. Frank A. Christoph wrote: > The number of times GHC has been too slow and > memory-hungry for me indicates that Haskell is not suitable for writing > anything as general-purpose as a compiler. That's a fairly naive remark. I could write you a really slow and fat C++ compiler i C if you like. There are a number of reasons why it's too early judge. For a stunning example, you should look at Niklas Rojemo's thesis about NHC. Now there's a space-tight compiler (although slow). Having said all that, yes, predictable memory behavior is IMHO the biggest problem of lazy language implementation these days. Juergen Pfitzenmaier wrote: > Maybe it is because GHC is doing some things that are difficult ;) Oh I know > a C++ compiler is handling complicated things (but only because the design of > C++ is brain damaged). Haskell is well designed (not neccessarily in every > detail but more as a whole) and has some features that need memory to compile. > I know of C++ programms with ca. 10.000 lines that take about 20 (twenty !!) > minutes to compile with egcs 1.1 on a 300Mhz pentium II. So there does GHC stand ? To make even the slightest useful statements based on these opservations we would have to know much more, at the very least, the level of optimization used. /Tommy
drop & take [was: fixing typos in Haskell-98]
S. Alexander Jacobson writes: > The correct definitions would be: > > take -2 -- drops the last 2 elements from the list > (takes everything except the last 2 elements) > drop -2 -- grabs the last 2 elements from the list > (drops everything except the last 2 elements) > These are also sane definitions.. IMHO, that would be the _insane_ definitions :-) Firstly, nothing suggests to me that rationale of such behaviour. Secondly, it would mean loosing an important set of laws: drop n . drop m === drop (n + m) take n . take m === take (n + m) (which, I note in passing, is broken also by suggestion A) Regards, Tommy
Re: drop & take [was: fixing typos in Haskell-98]
Chris Okasaki wrote: > For the people that share this sentiment, can you please > explain why ints that are too big should not similarly > give an error? I can see both being ok, or both being > errors. I just don't see why one should be ok and the > other an error. IMHO, both should be errors. If we really need, we can provide takeSloppy, takeBackwards, etc, but the default should be a tight as possible to catch errors. I still believe that take and drop should satisfy the compositional laws on legal arguments. Regards, Tommy
Re: A hard core game programmers view
"D. Tweed" wrote: > Another reason for the popularity of Perl is that it's _popular_ & > _ubiquitous_. Although I like Haskell and some other languages (e.g., > Mathematica, python, even C++) more than Perl, when I want to produce > something that I hope other people in my lab will use/contribute fixes to, > Perl's what I use (with much swearing & looking up in the manual). There's > only a few machines with a Haskell system available on them, whereas > everything has a Perl interpreter installed, and few people who are > comfortable with the language. That true, there are other contributing factors. Look and the following list, and notice how ever point is in striking contrast to Haskell: - Perl has one implementation - The implementation is rather lightweight *and* reasonable efficient - A large class of problems can be solved %90 very quickly with Perl - Perl has a _very_ complete library, including _all_ of unix api - The language has remained fairly stable - In the begining Perl advotates would tirelessly answer every question in comp.unix with some Perl code that answered the question - Perl is easy to install and is omnipresent Notice that the language itself is far from the whole story. In fact, while the language "features" will get you 90% of the solution fairly quickly, I know from professional experience that maintaining Perl scripts written by others can be a living nightmare and that the Quick'N'Dirty style promoted by Perl _will_ bite you in the end. > Of course, what can be done to help the start an epidemic `infecting' > people & machines with Haskell I don't know... Apart from the obvious of engineering better implementations and more complete libraries, we could publish code that solves common problems. Unfortunately it takes time to do properly, and in contrast to Perl, Haskell really shines on larger problems... /Tommy
Constrained instances?
Isn't it possible to constrain instances? I tried the following where the idea is to implement a simple monad, but one which can only pass and return values that are showable. newtype Show a => TracingEv a = TE (Int -> IO (Int,a)) unTE :: Show a => TracingEv a -> Int -> IO (Int,a) unTE (TE x) = x instance Monad TracingEv where return i = TE (\c -> do print c; putChar ':'; print i; putChar '\n' return (c+1,i)) m >>= f = TE (\c -> do (c',v) <- (unTE m) c (unTE (f v)) c') Neither GHC, nor hugs likes this. Hugs report: ERROR "MonadProblem.hs" (line 9): Cannot justify constraints in instance member binding *** Expression: return *** Type : Monad TracingEv => a -> TracingEv a *** Given context : Monad TracingEv *** Constraints : Show a ?? "Cannot justify constraints??" Isn't the case here rather that some constraints are lacking? GHC offers a little more explanation, but it remains cryptic: MonadProblem.hs:9: Could not deduce `Show a' from the context: () Probable cause: missing `Show a' in type signature for `return' arising from use of `TE' at MonadProblem.hs:9 In the right-hand side of an equation for `return': TE (\ c -> do print c putChar ':' print i putChar '\n' return (c + 1, i)) Sure there's a missing Show a, but I can't change the signature of return and it seems to me that Show a should follow from the constraint on TracingEv Is this a fundamental limitation? If so, why? Regards, Tommy
Desugarer for the happy Haskell parser?
First let me thank the authors of the prototype Haskell parser (Simon Marlow, Sven.Panne, and Noel Winstanley). It's a beautiful piece of work. While writing a desugarer for this, it occurred to me that somebody might already have done the work and be willing to share it, if not I'll make it available once it's finished. I looked at the desugarer from GHC, but it seems to different enough that it would be simpler to write a new, rather than adapt it to the Happy Haskell Parser. Best regards, Tommy
What happened to the GRIN project?
Long time ago I read The GRIN Project: A Highly Optimising Back End for Lazy Functional Languages Urban Boquist Thomas Johnson I thought it sounded very promising, but never heard anything since. Why? Didn't it work? Best regards, Tommy
Re: What happened to the GRIN project?
Thanks John, that's what I want to hear. Now the obvious follow up questions: 1) are anyone pursuing this line of work, and 2) is the software available? Best wishes, Tommy John Hughes writes: > The results of the GRIN experiment are written up in Urban Boquist's > PhD thesis from last year, which you can fetch from his home page: > > http://www.cs.chalmers.se/~boquist/ > > I found the results very exciting. It's true that GRIN uses a whole-program > analysis, but in practice that turned out not to be particularly expensive > (usually no more than 2% of compile time). If I remember rightly, Urban > compiled programs up to around 10,000 lines without a problem, although the > benchmarks in the thesis are much smaller. The code generated was on average > three-and-a-half times faster than code from GHC, and in the best case 40 > times faster! That extra order of magnitude seems to come from conservative > unfolding transformations which are effectively disabled in larger programs, > which raises the possibility that, with more aggressive unfolding, a further > substantial improvement in the running times of large programs might be > achievable. > > I recommend the thesis heartily. I enjoyed reading it very much. > > John Hughes
Pattern matching
I've looked at the pattern matching semantics as defined in the Haskell 98 report and there is few things I don't understand. 1) In Figure 3 (Semantics of Case Expressions, Part 1) clause c reads: case v of { p | g1 -> e1 ; ... | gn -> en where { decls } _ -> e' } = case e' of { y -> -- (where y is a completely new variable) case v of { p -> let { decls } in if g1 then e1 ... else if gn then en else y _ -> y }} My question is this: doesn't this mean that e' all of a sudden becomes strict, ie. that case v of { p | g1 -> e1 ; ... | gn -> en where { decls } _ -> _|_ } = _|_ ??? Why is it defined like this. 2) In the following clause (d) it is required that x1',...,xn' be completely new variables. Why? It seems to me that reusing x1,..,xn works just fine. Is there an alpha conversion requirement that I missed? Thanks, Tommy
Desugaring of top-level pattern bindings?
I'm puzzled by the Haskell 98 report, as it doesn't seem to explain how to desugar top-level pattern declarations, such as (x,y) = e In Section 4.4.3 (Function and Pattern Bindings) under Pattern Bindings it essentially says ``A simple pattern binding has form p = e. The pattern p is matched "lazily" as an irrefutable pattern, as if there were an implicit ~ in front of it. See the translation in Section 3.12.'' and then goes on the show how to eliminate guards. In Section 3.12 (Let Expressions) the translation given for let p = e1 in e0 are case e1 of ~p -> e0 if no variable in p appears free in e0, and let p = fix ( \ ~p -> e1) in e0 otherwise. Both of these translations only work in a expression context and thus does not work for top level bindings. It look like the required translation would look a lot like clause (d) from Figure 3, ie.: v = e x1 = case v of p -> x1 ... xn = case v of p -> xn where v is a new variable and x1,...,xn are the variables bound by p. Regards, Tommy