From laurent.deniau at cern.ch Fri Dec 1 14:03:22 2006 From: laurent.deniau at cern.ch (Laurent Deniau) Date: Fri Dec 1 14:01:51 2006 Subject: Standard (core) libraries initiative: rationale In-Reply-To: <149384522.20061127222809@gmail.com> References: <149384522.20061127222809@gmail.com> Message-ID: <45707C7A.1050301@cern.ch> Bulat Ziganshin wrote: > and this leads us to other question - whether this set and API of each > library should be fixed in language standard or it can evolve during > the time?... First, I should say that I am a Haskell newbie so consider what I say below as an 'external' point of view. About the language, after reading the Haskell98 report (and 'Haskell: the craft of functionnal programming') I found the language clean, simple, small and consistent. But I have also seen a lot of proposal for extensions on mailing lists and papers which may make Haskell' very difficult to learn because of the lack of history and evolution knowledge (the paper 'The History of Haskell' may help here). I think that keeping Haskell' minimal with a simple, consistent and clean syntax is very important to keep it attractive. This is probably the main reason why people come to Haskell (and why for example I will never use OCaml). It doesn't mean that new concept cannot be introduced (e.g. open data type), but it should be done with consistent and simple syntax in mind. About the libraries, I should say that I was a bit disappointed by the common use of the terms genericity and polymorphism (even in books). For example I have read many times that "length" is polymorphic or generic while it only computes the length of a list. It probably reflects that standard libraries do not provide enough *generic* API through the use of classes and overloading. If you look at Java evolution (not my favorite language), a lot of classes have been converted into interfaces to improve its flexibility and its evolution. In Haskell, most functions should be member of a generic API through classes and overloaded for common types like list (the paper 'Software Extension and Integration with Type Classes' may help here). This would incite developers to reuse the same API for their libs instead of creating dozen of variants of filter, map and fold and/or reinvent the wheel. If you look at language like CL or R which have thousands of functions, the vast majority of questions are 'how do I do this' because people are lost and don't even know where to start (the index is so huge). Finally, it may be worthwhile to include in the standard some description on some concept available in Haskell: laziness and monad. For example (I might be wrong), I understand monad simply as being: <> The *consequence* is that you can enforce *sequencing* because of the function evaluation semantic (function must be evaluated before you can use its returned value). And you can also *simulate* side effects because the 'thing' is never exposed. The latter being often not understood if you consider the FAQ 'how to get out of the IO monad?'. Finally, the rules associated with monads are just there to allow common usage, that is the composition of monad (e.g. in do notation) and the encapsulation of the 'thing' when entering the monad. Unless I am wrong, I have never seen a such simple description of monads which should allow programmers from other languages to understand the concept in a couple of minutes (better than talking about category theory ;-) . One could even consider monad as a design pattern since it is a common construction which solves a common problem. As a conclusion, I would say that I really like your initiative. my 2 c. Regards, ld. From iavor.diatchki at gmail.com Fri Dec 1 16:52:18 2006 From: iavor.diatchki at gmail.com (Iavor Diatchki) Date: Fri Dec 1 16:50:31 2006 Subject: character literal question Message-ID: <5ab17e790612011352k67800962i297c88e3796aa46d@mail.gmail.com> Hello, Is there a reason why we have to escape the character ' (apostrophe) when used in a character literal? For example, we have to write '\'' instead of '''. (With syntax highlighting, the second is a lot better looking than the first.) It seems that in this case we do not need the escape because a literal contains exactly one character. If there is no good reason for having the scape, I think that we should remove this restriction in Haskell'. -Iavor From twanvl at gmail.com Fri Dec 1 17:19:14 2006 From: twanvl at gmail.com (Twan van Laarhoven) Date: Fri Dec 1 17:17:18 2006 Subject: character literal question In-Reply-To: <5ab17e790612011352k67800962i297c88e3796aa46d@mail.gmail.com> References: <5ab17e790612011352k67800962i297c88e3796aa46d@mail.gmail.com> Message-ID: <4570AA62.5030308@gmail.com> Iavor Diatchki wrote: > Hello, > Is there a reason why we have to escape the character ' (apostrophe) > when used in a character literal? For example, we have to write '\'' > instead of '''. (With syntax highlighting, the second is a lot better > looking than the first.) It seems that in this case we do not need > the escape because a literal contains exactly one character. If there > is no good reason for having the scape, I think that we should remove > this restriction in Haskell'. > -Iavor If you really want you can also allow an unescapped backslash, '\'. The rules for parsing character literals would become something like: case input of ''' -> a single quote '\'' -> a single quote '\' -> a backslash '\..' -> an escape 'a' -> a normal character I'm not saying this is a good idea, just that it is possible. :) Twan From ndmitchell at gmail.com Fri Dec 1 17:56:49 2006 From: ndmitchell at gmail.com (Neil Mitchell) Date: Fri Dec 1 17:55:02 2006 Subject: character literal question In-Reply-To: <5ab17e790612011352k67800962i297c88e3796aa46d@mail.gmail.com> References: <5ab17e790612011352k67800962i297c88e3796aa46d@mail.gmail.com> Message-ID: <404396ef0612011456o2908193i801d45ed5e7704bb@mail.gmail.com> Hi > Is there a reason why we have to escape the character ' (apostrophe) > when used in a character literal? For example, we have to write '\'' > instead of '''. This is what Ada does. I think that's a reason enough to keep things the way they are. It does actually make syntax hilighting more complex, and introduces another special case. It's also no longer "the same" as strings, since """ doesn't mean "\"". Thanks Neil From ashley at semantic.org Fri Dec 1 20:30:51 2006 From: ashley at semantic.org (Ashley Yakeley) Date: Fri Dec 1 20:33:16 2006 Subject: character literal question In-Reply-To: <404396ef0612011456o2908193i801d45ed5e7704bb@mail.gmail.com> References: <5ab17e790612011352k67800962i297c88e3796aa46d@mail.gmail.com> <404396ef0612011456o2908193i801d45ed5e7704bb@mail.gmail.com> Message-ID: Neil Mitchell wrote: > This is what Ada does. I think that's a reason enough to keep things > the way they are. More obscure languages such as C/C++ and Java also happen to do the same thing. -- Ashley Yakeley From gdr at integrable-solutions.net Sat Dec 2 14:28:29 2006 From: gdr at integrable-solutions.net (Gabriel Dos Reis) Date: Sat Dec 2 14:32:36 2006 Subject: Standard (core) libraries initiative: rationale In-Reply-To: <45707C7A.1050301@cern.ch> References: <149384522.20061127222809@gmail.com> <45707C7A.1050301@cern.ch> Message-ID: Laurent Deniau writes: [...] | About the libraries, I should say that I was a bit disappointed by the | common use of the terms genericity and polymorphism (even in | books). For example I have read many times that "length" is | polymorphic or generic while it only computes the length of a list. I suspect that reflects a common view, that the list datatype is The materialization of the notion of sequence -- anything else is either obscure or marginal or perversion :-/ | It probably reflects that standard libraries do not provide enough | *generic* API through the use of classes and overloading. If you look | at Java evolution (not my favorite language), a lot of classes have | been converted into interfaces to improve its flexibility and its | evolution. In Haskell, most functions should be member of a generic | API through classes and overloaded for common types like list (the | paper 'Software Extension and Integration with Type Classes' may help | here). I agree with what you say. However, the trouble with is that a descent job at categorizing and implementing containers with type classes will require, at the minimum, multi-parameter type classes functional dependencies, associated types or equivalents. Those topics seem to be subject of heated debates among seasoned Haskellers. Personally, I'm looking forward to a standardization of multit-parameter type classes with functional dependency -- at least a blessing of the parts that "work". Simon PJ has an excellent paper on "bulk types with class" that you might want to consult for some thorny issues. [...] | Finally, the rules associated with monads are just there to | allow common usage, that is the composition of monad (e.g. in do | notation) and the encapsulation of the 'thing' when entering the | monad. And change the name "monad" to something less scary for common programmers too? :-) -- Gaby From iavor.diatchki at gmail.com Sat Dec 2 16:40:46 2006 From: iavor.diatchki at gmail.com (Iavor Diatchki) Date: Sat Dec 2 16:38:56 2006 Subject: character literal question In-Reply-To: <404396ef0612011456o2908193i801d45ed5e7704bb@mail.gmail.com> References: <5ab17e790612011352k67800962i297c88e3796aa46d@mail.gmail.com> <404396ef0612011456o2908193i801d45ed5e7704bb@mail.gmail.com> Message-ID: <5ab17e790612021340s241205a7m7ea892af63a44ef6@mail.gmail.com> Hello, > It does actually make syntax hilighting more complex, and introduces > another special case. How is that another special case? If anything, it seems to be removing a special case because there is no need for an escape of the form \'. Do you have a concrete example of what it complicates? > It's also no longer "the same" as strings, since > """ doesn't mean "\"". Fair enough, but it is easy to explain why these are different. Can we explain why we need to escape the quote in character literals? So far we have: (i) we want to be different from Ada, and (ii) we want to do the same as C and Java. A nice property of the small change that I proposed is that to switch between a singleton string and a character we just need to change the quotes. With the current notation we have to also add a backslash if the string happened to be "'", which seems redundant. Anyways, this is not a big thing but it seems like a wrinkle that could be fixed. -Iavor From droundy at darcs.net Wed Dec 6 20:08:33 2006 From: droundy at darcs.net (David Roundy) Date: Wed Dec 6 20:06:30 2006 Subject: infix MPTC? Message-ID: <20061207010831.GH1935@abridgegame.org> I was just thinking today. Is there any reason we couldn't have infix multiparameter typeclasses? For typeclasses standing as witnesses of relationships it'd be much clearer, for example to have something like (a :<: b) rather than the always-vague (LT a b) which either reads the same as the infix version or backwards. This isn't so much a proposal as a query regarding reasonableness. I certainly wouldn't like to have precedence rules for type classes, but perhaps if you simply always required parentheses it'd be more readable than always requiring prefix notation, and yet still not too insane to parse? -- David Roundy Department of Physics Oregon State University From dons at cse.unsw.edu.au Wed Dec 6 20:39:35 2006 From: dons at cse.unsw.edu.au (Donald Bruce Stewart) Date: Wed Dec 6 20:37:33 2006 Subject: infix MPTC? In-Reply-To: <20061207010831.GH1935@abridgegame.org> References: <20061207010831.GH1935@abridgegame.org> Message-ID: <20061207013935.GD15169@cse.unsw.EDU.AU> droundy: > I was just thinking today. Is there any reason we couldn't have infix > multiparameter typeclasses? For typeclasses standing as witnesses of > relationships it'd be much clearer, for example to have something like > (a :<: b) rather than the always-vague (LT a b) which either reads the > same as the infix version or backwards. > > This isn't so much a proposal as a query regarding reasonableness. I > certainly wouldn't like to have precedence rules for type classes, but > perhaps if you simply always required parentheses it'd be more readable > than always requiring prefix notation, and yet still not too insane to > parse? I think they are valid now! Here's an example: class a :=: b where from: http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#infix-tycons Perhaps underappreciated, along with: f :: (a :=: b) => a -> b -- Don From droundy at darcs.net Wed Dec 6 21:15:27 2006 From: droundy at darcs.net (David Roundy) Date: Wed Dec 6 21:13:25 2006 Subject: infix MPTC? In-Reply-To: <20061207013935.GD15169@cse.unsw.EDU.AU> References: <20061207010831.GH1935@abridgegame.org> <20061207013935.GD15169@cse.unsw.EDU.AU> Message-ID: <20061207021525.GK1935@abridgegame.org> On Thu, Dec 07, 2006 at 12:39:35PM +1100, Donald Bruce Stewart wrote: > droundy: > > I was just thinking today. Is there any reason we couldn't have infix > > multiparameter typeclasses? For typeclasses standing as witnesses of > > relationships it'd be much clearer, for example to have something like > > (a :<: b) rather than the always-vague (LT a b) which either reads the > > same as the infix version or backwards. > > [...] > > I think they are valid now! Silly me! I didn't even think to try! Nice. And thanks! -- David Roundy Department of Physics Oregon State University From john at repetae.net Fri Dec 8 05:33:47 2006 From: john at repetae.net (John Meacham) Date: Fri Dec 8 05:31:15 2006 Subject: New Layout Rule In-Reply-To: <20061207020728.GB7573@momenergy.repetae.net> References: <20061207003441.GA15169@cse.unsw.EDU.AU> <20061207005658.GA7573@momenergy.repetae.net> <1165455421.11284.27.camel@meteor.newtonlabs.com> <20061207020728.GB7573@momenergy.repetae.net> Message-ID: <20061208103347.GH8493@momenergy.repetae.net> Motivated by some recent discussion, I thought I would explore the possibilty of formalizing the haskell layout rule without the dreaded parse-error clause, as in, one that can be completly handled by the lexer. motivated by that I have written a little program that takes a haskell file with layout on stdin and spits out one without layout on stdout. it can be gotten here: darcs get http://repetae.net/repos/getlaid/ the code is designed to make the layout algorithm completly transparent, so that we might experiment with it. The function layout in 'Layout.hs' is the single and complete layout algorithm and the only thing that need be modified by experimentors. I have come up with a simple improvement to the algorithm given in the paper that seems to catch a very large number of layouts. basically, whenever it comes across something that must come in matched pairs (, ), case of, if then. it pushes a special context onto the stack, when it comes across the closing token, it pops every layout context down to the special context. there is a special case for "in" that causes it to pop only up to the last context created with a "let", but not further. here is the complete algorithm (with my modification, sans the parse-error rule): > data Token = Token String | TokenVLCurly String !Int | TokenNL !Int deriving(Show) > > data Context = NoLayout | Layout String !Int > > -- the string on 'Layout' and 'TokenVLCurly' is the token that > -- created the layout, always one of "where", "let", "do", or "of" > > layout :: [Token] -> [Context] -> [Token] > layout (TokenNL n:rs) (Layout h n':ls) > | n == n' = semi:layout rs (Layout h n':ls) > | n > n' = layout rs (Layout h n':ls) > | n < n' = rbrace:layout (TokenNL n:rs) ls > layout (TokenNL _:rs) ls = layout rs ls > layout (TokenVLCurly h n:rs) (Layout h' n':ls) > | n >= n' = lbrace:layout rs (Layout h n:Layout h' n':ls) > | otherwise = error "inner layout can't be shorter than outer one" > layout (TokenVLCurly h n:rs) ls = lbrace:layout rs (Layout h n:ls) > layout (t@(Token s):rs) ls | s `elem` fsts layoutBrackets = t:layout rs (NoLayout:ls) > layout (t@(Token s):rs) ls | s `elem` snds layoutBrackets = case ls of > Layout _ _:ls -> rbrace:layout (t:rs) ls > NoLayout:ls -> t:layout rs ls > [] -> error $ "unexpected " ++ show s > layout (t@(Token "in"):rs) ls = case ls of > Layout "let" n:ls -> rbrace:t:layout rs ls > Layout _ _:ls -> rbrace:layout (t:rs) ls > ls -> t:layout rs ls > layout (t:rs) ls = t:layout rs ls > layout [] (Layout _ n:ls) = rbrace:layout [] ls > layout [] [] = [] > > layoutBrackets = [ ("case","of"), ("if","then"), > ("(",")"), ("[","]"), ("{","}") ] now. there are a few cases it doesn't catch. the hanging case at the end of a guard for instance, I believe this can be solved easily by treating '|' and '=' as opening and closing pairs in lets and wheres '|' and '->' as opening and closing pairs in case bodies. it is easy to see which one you are in by looking at the context stack. commas are trickier and are the only other case I think we need to consider. I welcome people to experiment and send patches or brainstorm ideas, I have what I believe is a full solution percolating in my head, but am unhappy with it, I am going to sleep on it and see if it crystalizes by morning. In the meantime, perhaps someone can come up with something more elegant for dealing with the remaining cases. or at least find some real programs that this code breaks down on! (bug fixes for the lexer and everything are very much welcome. it will probably choke on some ghc extensions that would be trivial to add to the alex grammar) John -- John Meacham - ?repetae.net?john? From igloo at earth.li Fri Dec 8 10:26:30 2006 From: igloo at earth.li (Ian Lynagh) Date: Fri Dec 8 10:24:21 2006 Subject: New Layout Rule In-Reply-To: <20061208103347.GH8493@momenergy.repetae.net> References: <20061207003441.GA15169@cse.unsw.EDU.AU> <20061207005658.GA7573@momenergy.repetae.net> <1165455421.11284.27.camel@meteor.newtonlabs.com> <20061207020728.GB7573@momenergy.repetae.net> <20061208103347.GH8493@momenergy.repetae.net> Message-ID: <20061208152630.GA9261@matrix.chaos.earth.li> On Fri, Dec 08, 2006 at 02:33:47AM -0800, John Meacham wrote: > Motivated by some recent discussion, I thought I would explore the > possibilty of formalizing the haskell layout rule without the dreaded > parse-error clause, as in, one that can be completly handled by the > lexer. There was some discussion about that a while ago on this list, e.g. http://www.haskell.org/pipermail/haskell-prime/2006-March/000915.html and other subthreads in that thread. I'd still love to see a replacement which can be a separate phase between lexing and parsing, even if it means we need to lay some things out differently or tweak other bits of the syntax. Thanks Ian From john at repetae.net Fri Dec 8 16:50:54 2006 From: john at repetae.net (John Meacham) Date: Fri Dec 8 16:48:15 2006 Subject: New Layout Rule In-Reply-To: <20061208152630.GA9261@matrix.chaos.earth.li> References: <20061207003441.GA15169@cse.unsw.EDU.AU> <20061207005658.GA7573@momenergy.repetae.net> <1165455421.11284.27.camel@meteor.newtonlabs.com> <20061207020728.GB7573@momenergy.repetae.net> <20061208103347.GH8493@momenergy.repetae.net> <20061208152630.GA9261@matrix.chaos.earth.li> Message-ID: <20061208215054.GI8493@momenergy.repetae.net> On Fri, Dec 08, 2006 at 03:26:30PM +0000, Ian Lynagh wrote: > On Fri, Dec 08, 2006 at 02:33:47AM -0800, John Meacham wrote: > > Motivated by some recent discussion, I thought I would explore the > > possibilty of formalizing the haskell layout rule without the dreaded > > parse-error clause, as in, one that can be completly handled by the > > lexer. > > There was some discussion about that a while ago on this list, e.g. > http://www.haskell.org/pipermail/haskell-prime/2006-March/000915.html > and other subthreads in that thread. > > I'd still love to see a replacement which can be a separate phase > between lexing and parsing, even if it means we need to lay some things > out differently or tweak other bits of the syntax. "let" isn't an issue (at least not for the reason specified in that mail). It is taken care of properly in the version I posted. the trick is to annotate each layout context with what caused it to occur. when you reach an "in" rather than popping up to the most recent NoLayout (as you would with a bracket) you pop up to the most recent layout context that was started with a "let". (if such a context doesn't exist, it is a syntax error) John -- John Meacham - ?repetae.net?john? From john at repetae.net Sat Dec 9 23:52:09 2006 From: john at repetae.net (John Meacham) Date: Sat Dec 9 23:49:31 2006 Subject: New Layout Rule take 2 In-Reply-To: <20061208103347.GH8493@momenergy.repetae.net> References: <20061207003441.GA15169@cse.unsw.EDU.AU> <20061207005658.GA7573@momenergy.repetae.net> <1165455421.11284.27.camel@meteor.newtonlabs.com> <20061207020728.GB7573@momenergy.repetae.net> <20061208103347.GH8493@momenergy.repetae.net> Message-ID: <20061210045209.GJ8493@momenergy.repetae.net> I have made some improvements to the algorithm, and I am happy to say that with some minor tweaks, it correctly lays out the programs in the nofib suite. the algorithm is not much more complicated than the current one in the report, but doesn't have the parse-error rule. it does require a single token of lookahead to look for an "in". darcs get http://repetae.net/repos/getlaid/ I have also added a mode so it can work as a ghc preprocesor, allowing very easy testing. just compile with. ghc -pgmF /path/to/getlaid -F --make Main.hs and it will automatically process all your files. Now, it isn't perfect. I can construct pathological examples that the old rule would parse, but this one won't. however, if those examples don't actually occur in practice, then that is not so much an issue. my program doesn't handle many non-haskell 98 extensions, but can probably be easily modified to do so. John -- John Meacham - ?repetae.net?john? From twanvl at gmail.com Sun Dec 10 18:40:33 2006 From: twanvl at gmail.com (Twan van Laarhoven) Date: Sun Dec 10 18:38:17 2006 Subject: Type sections Message-ID: <457C9AF1.6050904@gmail.com> Since operators are allowed in type and class names, I think it would make sense if the section notation was also allowed. In particular the Reader monad would be a little bit nicer: > instance Monad (e ->) where ... And maybe type level programming can benefit as well. Twan From schneegloeckchen at gmx.li Sun Dec 10 19:06:19 2006 From: schneegloeckchen at gmx.li (mm) Date: Sun Dec 10 18:58:28 2006 Subject: Are pattern guards obsolete? Message-ID: <20061211000619.GA8058@manthe.gotdns.org> Hello, recently I read about pattern guards which are a candidate for Haskell'. As I understand them, their purpose is to provide an easier way to write functions like (taken from the wiki, it does not run): clunky env var1 var1 = case lookup env var1 of Nothing -> fail Just val1 -> case lookup env var2 of Nothing -> fail Just val2 -> val1 + val2 where fail = var1 + var2 Wouldn't > clunky :: Num a => [(a, a)] -> a -> a -> a > clunky env var1 var2 = case (lookup var1 env, lookup var2 env) of > (Just v1, Just v2) -> v1 + v2 > _ -> var1 + var2 be simple enough to make a syntax change superflous? It is so simple, that there is no need for `fail` in Haskell or Haskell' :) schneegloeckchen From dons at cse.unsw.edu.au Sun Dec 10 19:04:48 2006 From: dons at cse.unsw.edu.au (Donald Bruce Stewart) Date: Sun Dec 10 19:02:37 2006 Subject: Are pattern guards obsolete? In-Reply-To: <20061211000619.GA8058@manthe.gotdns.org> References: <20061211000619.GA8058@manthe.gotdns.org> Message-ID: <20061211000448.GA22250@cse.unsw.EDU.AU> schneegloeckchen: > Hello, > > recently I read about pattern guards which are a candidate for Haskell'. > > As I understand them, their purpose is to provide an easier way to write > functions like (taken from the wiki, it does not run): > > clunky env var1 var1 = case lookup env var1 of > Nothing -> fail > Just val1 -> case lookup env var2 of > Nothing -> fail > Just val2 -> val1 + val2 > where > fail = var1 + var2 > > > Wouldn't > > > clunky :: Num a => [(a, a)] -> a -> a -> a > > clunky env var1 var2 = case (lookup var1 env, lookup var2 env) of > > (Just v1, Just v2) -> v1 + v2 > > _ -> var1 + var2 > > be simple enough to make a syntax change superflous? It is so simple, that there > is no need for `fail` in Haskell or Haskell' :) There's been a previous discussion on this[1]. The joy of pattern guards reveals once you have more conditions. Consider this real world example: clean_ s| Just _ <- no_io `matchRegex` s = "No IO allowed\n" | Just _ <- terminated `matchRegex` s = "Terminated\n" | Just _ <- hput `matchRegex` s = "Terminated\n" | Just _ <- outofmem `matchRegex` s = "Terminated\n" | Just _ <- stack_o_f `matchRegex` s = "Stack overflow\n" | Just _ <- loop `matchRegex` s = "Loop\n" | Just _ <- undef `matchRegex` s = "Undefined\n" | Just _ <- type_sig `matchRegex` s = "Add a type signature\n" | Just (_,m,_,_) <- ambiguous `matchRegexAll` s = m | Just (_,_,b,_) <- inaninst `matchRegexAll` s = clean_ b | Just (_,_,b,_) <- irc `matchRegexAll` s = clean_ b | Just (_,m,_,_) <- nomatch `matchRegexAll` s = m | Just (_,m,_,_) <- notinscope `matchRegexAll` s = m | Just (_,m,_,_) <- hsplugins `matchRegexAll` s = m | Just (a,_,_,_) <- columnnum `matchRegexAll` s = a | Just (a,_,_,_) <- extraargs `matchRegexAll` s = a | Just (_,_,b,_) <- filename' `matchRegexAll` s = clean_ b | Just (a,_,b,_) <- filename `matchRegexAll` s = a ++ clean_ b | Just (a,_,b,_) <- filepath `matchRegexAll` s = a ++ clean_ b | Just (a,_,b,_) <- runplugs `matchRegexAll` s = a ++ clean_ b | otherwise = s -- Don 1. http://www.haskell.org/pipermail/haskell-prime/2006-September/001689.html From ndmitchell at gmail.com Sun Dec 10 20:43:59 2006 From: ndmitchell at gmail.com (Neil Mitchell) Date: Sun Dec 10 20:41:43 2006 Subject: Are pattern guards obsolete? In-Reply-To: <20061211000448.GA22250@cse.unsw.EDU.AU> References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> Message-ID: <404396ef0612101743l68dfc7dvf99ccae6d20e215@mail.gmail.com> Hi > > clunky env var1 var1 = case lookup env var1 of > > Nothing -> fail > > Just val1 -> case lookup env var2 of > > Nothing -> fail > > Just val2 -> val1 + val2 > > where > > fail = var1 + var2 > > > > > > Wouldn't > > > > > clunky :: Num a => [(a, a)] -> a -> a -> a > > > clunky env var1 var2 = case (lookup var1 env, lookup var2 env) of > > > (Just v1, Just v2) -> v1 + v2 > > > _ -> var1 + var2 The main advantage of pattern guards (to me at least) is that they can appear on the LHS, so failing to match can result in fall through. Everything else has to come on the RHS, meaning you have pick the RHS by this point. This is bad because it now means two entirely separate alternatives just got merged into one, reducing program readability. I would love this to be in Haskell'. In fact, if we could only pick one thing to go in Haskell', I would pick pattern guards. I would have used pattern guards about 15 times today, if they were in Haskell. Compare that to rank-2 types (never needed), MPTC (needed once ever) etc. and you can see why I want this! Thanks Neil From tomasz.zielonka at gmail.com Mon Dec 11 03:13:34 2006 From: tomasz.zielonka at gmail.com (Tomasz Zielonka) Date: Mon Dec 11 03:11:19 2006 Subject: Type sections In-Reply-To: <457C9AF1.6050904@gmail.com> References: <457C9AF1.6050904@gmail.com> Message-ID: <20061211081334.GA4926@lambda> On Mon, Dec 11, 2006 at 12:40:33AM +0100, Twan van Laarhoven wrote: > Since operators are allowed in type and class names, I think it would > make sense if the section notation was also allowed. In particular the > Reader monad would be a little bit nicer: > > instance Monad (e ->) where ... > And maybe type level programming can benefit as well. I wonder about (-> e) - by analogy to expression sections it could be desugared to a type-level lambda. AFAIU, type-level lambdas are avoided when you want terminating type-checking. IIUC, you have an equivalent power if you turn on certain GHC's extensions. Perhaps with those extensions we could have type-level lambdas too? Or we have them already, somehow disguised? Please tell me, if I am talking nonsense. Best regards Tomasz From loeh at iai.uni-bonn.de Mon Dec 11 04:30:12 2006 From: loeh at iai.uni-bonn.de (Andres Loeh) Date: Mon Dec 11 04:22:11 2006 Subject: Type sections In-Reply-To: <20061211081334.GA4926@lambda> References: <457C9AF1.6050904@gmail.com> <20061211081334.GA4926@lambda> Message-ID: <20061211093011.GS21003@iai.uni-bonn.de> > I wonder about (-> e) - by analogy to expression sections it could be > desugared to a type-level lambda. AFAIU, type-level lambdas are avoided > when you want terminating type-checking. IIUC, you have an equivalent > power if you turn on certain GHC's extensions. Perhaps with those > extensions we could have type-level lambdas too? Or we have them > already, somehow disguised? You're right. Type sections are problematic, because if partially applied, they'd require type-level lambda. Type lambda is definitely not going to be in Haskell', and I'm not in favour of adding some crippled form of type sections that must always be fully applied. Cheers, Andres From gale at sefer.org Tue Dec 12 20:49:11 2006 From: gale at sefer.org (Yitz Gale) Date: Tue Dec 12 22:02:47 2006 Subject: Are pattern guards obsolete? References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> Message-ID: Donald Bruce Stewart writes: > The joy of pattern guards > reveals once you have more conditions. Of course, this is not really the joy of pattern guards. It is the joy of monads, with perhaps a few character strokes saved by a confusing overloading of (<-). But some people do seem to be used to this notation by now. So perhaps a good compromise would be to use a different operator for pattern guards, e.g. (<<-), instead of (<-). What do you say? Yitz From flippa at flippac.org Tue Dec 12 22:31:08 2006 From: flippa at flippac.org (Philippa Cowderoy) Date: Tue Dec 12 22:26:41 2006 Subject: Are pattern guards obsolete? In-Reply-To: References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> Message-ID: On Wed, 13 Dec 2006, Yitz Gale wrote: > Donald Bruce Stewart writes: > > The joy of pattern guards > > reveals once you have more conditions. > > Of course, this is not really the joy of > pattern guards. It is the joy of monads, > with perhaps a few character strokes > saved by a confusing overloading of (<-). > I don't find it any more confusing than the overloading of ->. Note that it's not (<-) - it's not an operator. -- flippa@flippac.org Sometimes you gotta fight fire with fire. Most of the time you just get burnt worse though. From gale at sefer.org Wed Dec 13 06:09:59 2006 From: gale at sefer.org (Yitzchak Gale) Date: Wed Dec 13 06:07:48 2006 Subject: Are pattern guards obsolete? In-Reply-To: References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> Message-ID: <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> Donald Bruce Stewart wrote: >>> The joy of pattern guards >>> reveals once you have more conditions. I wrote: >> Of course, this is not really the joy of >> pattern guards. It is the joy of monads, >> with perhaps a few character strokes >> saved by a confusing overloading of (<-). Philippa Cowderoy wrote: > I don't find it any more confusing than the overloading > of ->. You mean that it is used both for lambda abstractions and for functional dependencies? True, but those are so different that there is no confusion. > Note that it's not (<-) - it's not an operator. Right, it is syntactic sugar for a monad. But this syntax is already used in two places: do notation and list comprehensions. The semantics are exactly the same in both existing uses. The semantics of the proposed new use in pattern guards is quite different, as was discussed in the previous thread. Yet close enough to be confused. There seems to be a consensus that pattern guards are here to stay. So I am proposing to mitigate the damage somewhat by using a different but similar symbol . That matches the different but similar semantics. I mentioned (<<-) as one possibility. Regards, Yitz From gale at sefer.org Wed Dec 13 06:23:51 2006 From: gale at sefer.org (Yitzchak Gale) Date: Wed Dec 13 06:21:30 2006 Subject: Are pattern guards obsolete? In-Reply-To: <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> Message-ID: <2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com> Philippa Cowderoy wrote: >> I don't find it any more confusing than the overloading >> of ->. I wrote: > You mean that it is used both for lambda abstractions > and for functional dependencies? True, but those > are so different that there is no confusion. Oh, and case. Also quite different. But, hmm, perhaps that is also getting to be a bit much. In fact, now I think I recall seeing some mention of that in discussions about fundep syntax. Anyway, existing problems are not an excuse to repeat the mistake and make matters even worse. Regards, Yitz From flippa at flippac.org Wed Dec 13 07:55:52 2006 From: flippa at flippac.org (Philippa Cowderoy) Date: Wed Dec 13 07:51:26 2006 Subject: Are pattern guards obsolete? In-Reply-To: <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> Message-ID: On Wed, 13 Dec 2006, Yitzchak Gale wrote: > Yitzchak Gale wrote: > > > Of course, this is not really the joy of > > > pattern guards. It is the joy of monads, > > > with perhaps a few character strokes > > > saved by a confusing overloading of (<-). > > Philippa Cowderoy wrote: > > I don't find it any more confusing than the overloading > > of ->. > > You mean that it is used both for lambda abstractions > and for functional dependencies? True, but those > are so different that there is no confusion. > You missed out case statements. -- flippa@flippac.org "My religion says so" explains your beliefs. But it doesn't explain why I should hold them as well, let alone be restricted by them. From flippa at flippac.org Wed Dec 13 07:56:56 2006 From: flippa at flippac.org (Philippa Cowderoy) Date: Wed Dec 13 07:52:26 2006 Subject: Are pattern guards obsolete? In-Reply-To: <2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com> References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> <2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com> Message-ID: On Wed, 13 Dec 2006, Yitzchak Gale wrote: > Philippa Cowderoy wrote: > > > I don't find it any more confusing than the overloading > > > of ->. > > I wrote: > > You mean that it is used both for lambda abstractions > > and for functional dependencies? True, but those > > are so different that there is no confusion. > > Oh, and case. Also quite different. This is what I get for replying straight away! > Anyway, existing problems are not an excuse to > repeat the mistake and make matters even worse. > I think my point is that I'm not aware of many people who actually think this is a problem or get confused. -- flippa@flippac.org There is no magic bullet. There are, however, plenty of bullets that magically home in on feet when not used in exactly the right circumstances. From gale at sefer.org Wed Dec 13 08:45:17 2006 From: gale at sefer.org (Yitzchak Gale) Date: Wed Dec 13 08:42:52 2006 Subject: Are pattern guards obsolete? In-Reply-To: References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> <2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com> Message-ID: <2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com> Philippa Cowderoy wrote: > This is what I get for replying straight away! Oh, no, I'm happy that you responded quickly. > I think my point is that I'm not aware of many people > who actually think this is a problem or get confused. Well, I don't mean that this is something that experienced Haskell programmers will stop and scratch their heads over. But the more of these kinds of inconsistencies you have, the worse it is for a programming language. The effect is cumulative. When there are too many of them, they make the language feel heavy, complex, and inelegant. They increase the number of careless errors. They put off beginners. Regards, Yitz From iavor.diatchki at gmail.com Wed Dec 13 12:33:30 2006 From: iavor.diatchki at gmail.com (Iavor Diatchki) Date: Wed Dec 13 12:31:05 2006 Subject: Are pattern guards obsolete? In-Reply-To: <2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com> References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> <2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com> <2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com> Message-ID: <5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> Hi, I am not clear why you think the current notation is confusing... Could you give a concrete example? I am thinking of something along the lines: based on how "<-" works in list comprehensions and the do notation, I would expect that pattern guards do XXX but instead, they confusingly do YYY. I think that this will help us keep the discussion concrete. -Iavor On 12/13/06, Yitzchak Gale wrote: > Philippa Cowderoy wrote: > > This is what I get for replying straight away! > > Oh, no, I'm happy that you responded quickly. > > > I think my point is that I'm not aware of many people > > who actually think this is a problem or get confused. > > Well, I don't mean that this is something that experienced > Haskell programmers will stop and scratch their heads > over. > > But the more of these kinds of inconsistencies you have, > the worse it is for a programming language. The effect > is cumulative. When there are too many of them, they make > the language feel heavy, complex, and inelegant. They > increase the number of careless errors. They put > off beginners. > > Regards, > Yitz > _______________________________________________ > Haskell-prime mailing list > Haskell-prime@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-prime > From apfelmus at quantentunnel.de Wed Dec 13 13:33:29 2006 From: apfelmus at quantentunnel.de (apfelmus@quantentunnel.de) Date: Wed Dec 13 13:34:02 2006 Subject: Are pattern guards obsolete? In-Reply-To: <5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> <2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com> <2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com> <5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> Message-ID: Iavor Diatchki wrote: > I am not clear why you think the current notation is confusing... > Could you give a concrete example? I am thinking of something along > the lines: based on how "<-" works in list comprehensions and the do > notation, I would expect that pattern guards do XXX but instead, they > confusingly do YYY. I think that this will help us keep the > discussion concrete. Pattern guards basically are a special-case syntactic sugar for (instance MonadPlus Maybe). The guard foo m x | empty m = bar | Just r <- lookup x m, r == 'a' = foobar directly translates to foo m x = fromMaybe $ (do { guard (empty m); return bar;}) `mplus` (do {Just r <- return (lookup m x); guard (r == 'a'); return foobar;}) The point is that the pattern guard notation Just r <- lookup m x does *not* translate to itself but to Just r <- return (lookup m x) in the monad. The <- in the pattern guard is a simple let binding. There is no monadic action on the right hand side of <- in the pattern guard. Here, things get even more confused because (lookup m x) is itself a Maybe type, so the best translation into (MonadPlus Maybe) actually would be r <- lookup m x Regards, apfelmus From claus.reinke at talk21.com Wed Dec 13 13:18:15 2006 From: claus.reinke at talk21.com (Claus Reinke) Date: Wed Dec 13 13:43:39 2006 Subject: Are pattern guards obsolete? References: <20061211000619.GA8058@manthe.gotdns.org><20061211000448.GA22250@cse.unsw.EDU.AU><2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com><2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com><2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com> <5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> Message-ID: <01fc01c71ee3$0fe71380$36158351@cr3lt> > I am not clear why you think the current notation is confusing... > Could you give a concrete example? I am thinking of something along > the lines: based on how "<-" works in list comprehensions and the do > notation, I would expect that pattern guards do XXX but instead, they > confusingly do YYY. I think that this will help us keep the > discussion concrete. consider the following examples: -- do-notation: explicit return; explicit guard; monadic result d _ = do { Just b <- return (Just True); guard b; return 42 } -- list comprehension: explicit return; implicit guard; monadic (list) result lc _ = [ 42 | Just b <- return (Just True), b ] -- pattern guard: implicit return; implicit guard; non-monadic result pg _ | Just b <- Just True, b = 42 in spite of their similarity, all of these constructs handle some of the monadic aspects differently. the translations of pattern guards not only embed statements in "guard", they also embed the right hand sides of generators in "return". translations of list comprehensions only lift statements. translation of do-notation lifts neither statements nor generators. does this clarify things? Claus From ndmitchell at gmail.com Wed Dec 13 15:21:02 2006 From: ndmitchell at gmail.com (Neil Mitchell) Date: Wed Dec 13 15:18:37 2006 Subject: Are pattern guards obsolete? In-Reply-To: <01fc01c71ee3$0fe71380$36158351@cr3lt> References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> <2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com> <2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com> <5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> <01fc01c71ee3$0fe71380$36158351@cr3lt> Message-ID: <404396ef0612131221l3bc741f1x12a9404c2532bb34@mail.gmail.com> Hi > in spite of their similarity, all of these constructs handle some of the > monadic aspects differently. the translations of pattern guards not only > embed statements in "guard", they also embed the right hand sides of > generators in "return". translations of list comprehensions only lift > statements. translation of do-notation lifts neither statements nor > generators. > > does this clarify things? No. Pattern guards are "obvious", they could only work in one particular way, and they do work that way. They make common things easier, and increase abstraction. If your only argument against them requires category theory, then I'd say that's a pretty solid reason for them going in. The argument that people seem to be making is that they are confusing, I completely disagree. f value | Just match <- lookup value list = g match Without thinking too hard, I am curious how anyone could get the meaning of this wrong if they understand the rest of Haskell. Can you show a concrete example, where you think a user would get confused? Thanks Neil From claus.reinke at talk21.com Wed Dec 13 21:40:05 2006 From: claus.reinke at talk21.com (Claus Reinke) Date: Wed Dec 13 21:37:44 2006 Subject: Are pattern guards obsolete? References: <20061211000619.GA8058@manthe.gotdns.org> <20061211000448.GA22250@cse.unsw.EDU.AU> <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> <2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com> <2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com> <5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> <01fc01c71ee3$0fe71380$36158351@cr3lt> <404396ef0612131221l3bc741f1x12a9404c2532bb34@mail.gmail.com> Message-ID: <032501c71f29$2abfc6c0$36158351@cr3lt> >> does this clarify things? > > No. Pattern guards are "obvious", they could only work in one > particular way, and they do work that way. They make common things > easier, and increase abstraction. If your only argument against them > requires category theory, then I'd say that's a pretty solid reason > for them going in. sigh.. slow down please, will you? you addressed this reply to me. yet I have been careful, each time this topic comes up, to argue neither in favour nor against pattern guards. instead, my purpose has been to clarify misconceptions, eg., by demonstrating how pattern guards, even though they do add substantial convenience, do not add fundamentally new expressiveness (they can be replaced by a local rewrite), or in this case by providing the examples Iavor asked for, showing the difference in three uses of '<-' as generators and booleans as guards. I do not mind if pattern guards make it into Haskell, precisely because I know how to sugar them away - once all implementations support them, I might even use them more. Nevertheless, I wanted to support Yitzchak's argument, namely that '<-' is used for generators in monadic contexts, but its use in pattern guards is different from that in list comprehensions and do. pattern guards are useful, once explained, but there is nothing particularly obvious about them, nor is there only one way to formulate them: the usual argument that they are just list comprehension syntax transferred to guards breaks down because of the differences Yitzchak is concerned about, and the correspondent claiming to be apfelmus has already shown that a direct embedding of Maybes would be at least as natural as the current implicit embedding into the effect-free part of an unknown monad. > The argument that people seem to be making is that they are confusing, > I completely disagree. > > f value | Just match <- lookup value list = g match > > Without thinking too hard, I am curious how anyone could get the > meaning of this wrong if they understand the rest of Haskell. Can you > show a concrete example, where you think a user would get confused? sure, the one you gave right there. to be consistent with other uses of '<-' as a generator, I'd expect to write either f value | match <- lookup value list = g match or f value | Just match <- return (lookup value list) = g match Claus From dave at zednenem.com Wed Dec 13 23:00:00 2006 From: dave at zednenem.com (Dave Menendez) Date: Wed Dec 13 22:57:36 2006 Subject: Are pattern guards obsolete? In-Reply-To: <2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com> Message-ID: Yitzchak Gale writes: > Philippa Cowderoy wrote: > >> I don't find it any more confusing than the overloading > >> of ->. > > I wrote: > > You mean that it is used both for lambda abstractions > > and for functional dependencies? True, but those > > are so different that there is no confusion. > > Oh, and case. Also quite different. Also type and kind signatures. The use in case and lambda abstractions strike me as analogous. They both have a pattern to the left and an expression to the right. -- David Menendez | "In this house, we obey the laws | of thermodynamics!" From claus.reinke at talk21.com Thu Dec 14 06:07:25 2006 From: claus.reinke at talk21.com (Claus Reinke) Date: Thu Dec 14 06:06:17 2006 Subject: strictly matching monadic let and overloaded Bool (was: Are pattern guards obsolete?) References: <20061211000619.GA8058@manthe.gotdns.org><20061211000448.GA22250@cse.unsw.EDU.AU><2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com><2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com><2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com><5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> <01fc01c71ee3$0fe71380$36158351@cr3lt> Message-ID: <004a01c71f70$342533c0$5f057ad5@cr3lt> > consider the following examples: > > -- do-notation: explicit return; explicit guard; monadic result > d _ = do { Just b <- return (Just True); guard b; return 42 } > > -- list comprehension: explicit return; implicit guard; monadic (list) result > lc _ = [ 42 | Just b <- return (Just True), b ] > > -- pattern guard: implicit return; implicit guard; non-monadic result > pg _ | Just b <- Just True, b = 42 This ongoing discussion has made me curious about whether we could actually get rid of these irregularities in the language, without losing any of the features we like so much. === attempt 1 (a) boolean statements vs guards this looks straightforward. Bool is a type, so can never be an instance of constructor class Monad, so a boolean statement in a monadic context is always invalid at the moment. that means we could simply extend our syntactic sugar to take account of types, and read every ((e :: Bool) :: Monad m => m _) in a statement of a do block as a shorthand for (guard (e :: Bool) :: Monad m => m ()) (b) missing return in pattern guards this could be made to fit the general pattern, if we had (return == id). that would put us into the Identity monad, which seems fine at first, since we only need return, bind, guard, and fail. unfortunately, those are only the requirements for a single pattern guard - to handle not just failure, but also fall-through, we also need mplus. which means that the Identity monad does not have enough structure, we need at least Maybe.. this first attempt leaves us with two problems. not only is (return==id) not sufficient for (b), but the suggested approach to (a) is also not very haskellish: instead of having syntactic sugar depend on type information, the typical haskell approach is to have type-independent sugar that introduces overloaded operations, such as fromInteger :: Num a => Integer -> a to be resolved by the usual type class machinery. addressing these two issues leads us to === attempt 2 (a) overloading Bool following the approach of Num and overloaded numeric literals, we could introduce a type class Boolean class Boolean b where fromBool :: Bool -> b instance Boolean Bool where fromBool = id and implicitly translate every literal expression of type Bool True ~~> fromBool True False ~~> fromBool False now we can embed Boolean statements as monadic statements simply by defining an additional instance instance MonadPlus m => Boolean (m ()) where fromBool = guard (b) adding a strictly matching monadic let we can't just have (return==id), and we do not want the hassle of having to write pattern <- return expr in pattern guards. the alternative of using let doesn't work either let pattern = expr because we do want pattern match failure to abort the pattern guard and lead to overall match failure and fall-through. so what we really seem to want is a shorthand notation for a strict variant of monadic let bindings. apfelmus suggested to use '<=' for this purpose, so that, wherever monadic generators are permitted pattern <= expr ~~> pattern <- return expr === returning to the examples, the approach of attempt 2 would allow us to write -- do-notation: implicit return; implicit guard; monadic result d _ = do { Just b <= Just True; b; return 42 } -- list comprehension: implicit return; implicit guard; monadic (list) result lc _ = [ 42 | Just b <= Just True, b ] -- pattern guard: implicit return; implicit guard; non-monadic result pg _ | Just b <= Just True, b = 42 almost resolving the irregularities, and permitting uniform handling of related syntactic constructs. hooray!-) I say "almost", because Bool permeates large parts of language and libraries, so one would need to check every occurence of the type and possibly replace Bool by (Boolean b => b). the Boolean Bool instance should mean that this process could be incremental (ie, even without replacements, things should still work, with more replacements generalizing more functionality, similar to the Int vs Integer issue), but that hope ought to be tested in practice. one issue arising in practice is that we would like to have fromBool :: MonadPlus m => Bool -> m a but the current definition of guard would fix the type to fromBool :: MonadPlus m => Bool -> m () which would require type annotations for Booleans used as guards. see the attached example for an easy workaround. on the positive side, this approach would not just make pattern guards more regular, but '<=' and 'MonadPlus m => Boolean (m ()) would be useful for monadic code in general. even better than that, those of use doing embedded DSLs in Haskell have been looking for a way to overload Bools for a long time, and the implicit 'Boolean b => fromBool :: Bool -> b' ought to get us started in the right direction. most likely, we would need more Bool-based constructs to be overloaded for Boolean, including at least a function equivalent for if-then-else: class If condition branch where if' :: condition -> branch -> branch -> branch instance If Bool e where if' c t e = if c then t else e instance Monad m => If (m Bool) (m a) where if' c t e = c >>= \b-> if b then t else e with associated desugaring if b then t else e ~~> if' b t e which would also enable us to get around another do notation annoyance, and write things like if (fmap read getLine :: IO Bool) then putStrLn "hi" else putStrLn "ho" all in all, this looks promising, so: thank you, Yitzchak, for insistencing in pointing out the inconsistencies of '<-' (it did cost me some sleep, but I like the results so far!-) I assume there might be downsides as well - any suggestions? Claus From claus.reinke at talk21.com Thu Dec 14 06:38:29 2006 From: claus.reinke at talk21.com (Claus Reinke) Date: Thu Dec 14 06:36:08 2006 Subject: strictly matching monadic let and overloaded Bool (was: Are patternguards obsolete?) References: <20061211000619.GA8058@manthe.gotdns.org><20061211000448.GA22250@cse.unsw.EDU.AU><2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com><2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com><2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com><5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com><01fc01c71ee3$0fe71380$36158351@cr3lt> <004a01c71f70$342533c0$5f057ad5@cr3lt> Message-ID: <007101c71f74$61500510$5f057ad5@cr3lt> > one issue arising in practice is that we would like to have > > fromBool :: MonadPlus m => Bool -> m a > > but the current definition of guard would fix the type to > > fromBool :: MonadPlus m => Bool -> m () > > which would require type annotations for Booleans used as guards. see the > attached example for an easy workaround. what attachment, you ask? sorry, lack of sleep - now attached to this message. claus -------------- next part -------------- A non-text attachment was scrubbed... Name: Boolean.hs Type: application/octet-stream Size: 794 bytes Desc: not available Url : http://www.haskell.org/pipermail/haskell-prime/attachments/20061214/0b886198/Boolean.obj From apfelmus at quantentunnel.de Thu Dec 14 09:04:55 2006 From: apfelmus at quantentunnel.de (apfelmus@quantentunnel.de) Date: Thu Dec 14 09:05:53 2006 Subject: "Higher order syntactic sugar" In-Reply-To: <004a01c71f70$342533c0$5f057ad5@cr3lt> References: <20061211000619.GA8058@manthe.gotdns.org><20061211000448.GA22250@cse.unsw.EDU.AU><2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com><2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com><2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com><5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> <01fc01c71ee3$0fe71380$36158351@cr3lt> <004a01c71f70$342533c0$5f057ad5@cr3lt> Message-ID: > apfelmus suggested to use '<=' for this purpose, so that, > wherever monadic generators > are permitted > > pattern <= expr ~~> pattern <- return expr It was to late when i realized that <= is already used as "smaller than or equal to" :) Obviously, the difference between the pattern guard <- and the monadic <- let easily slips by. I think this has to do with the fact that do-notation is not the natural style for MonadPlus Maybe, the natural style is more like the current syntax of pattern guards. I mean that one rarely hides a Just constructor like in do r <- lookup x map because returning Maybe is a very special case, there are many other constructors to match on where one wants fall-back semantics. Of course, every sum type can be projected to Maybe X =~= X + 1 but this involves boilerplate. In a sense, do-notation is just not appropriate for MonadPlus Maybe. It is somewhat unfortunate that while arrows, monads and pattern guards (= MonadPlus Maybe) could share the same syntax, it is not advisable to do so because this introduces quite annoying boilerplate. The most general syntax is too much for the special case. But there is something more canonical than completely disjoint syntax: in a sense, Claus' suggestions are about making the syntax for the special case a *subset* of the syntax for the more general one. The "partial order of syntax inclusion" should look something like Arrows \ \ MonadPlus \ / Monad Even though arrows are more general than monads (less theorems hold), they require more syntax. On the other hand, MonadPlus provides more than a monad, so it needs a new syntax, too. Remember that these are not the only computation abstractions. Syntactic sugar for pseudo-let-declarations (akin to MonadFix but order independent, can be embedded using observable sharing) is advisable, too. Only applicative functors behave very nicely and fit into current Haskell syntax (maybe that's the reason why they have been discovered only lately? :). In a sense, even ordinary Haskell (= pure functions) is only "syntactic sugar". Some "higher order syntactic sugar" melting machine bringing all these candies together would be very cool. Regards, apfelmus From claus.reinke at talk21.com Thu Dec 14 13:00:55 2006 From: claus.reinke at talk21.com (Claus Reinke) Date: Thu Dec 14 12:58:49 2006 Subject: "Higher order syntactic sugar" References: <20061211000619.GA8058@manthe.gotdns.org><20061211000448.GA22250@cse.unsw.EDU.AU><2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com><2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com><2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com><5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> <01fc01c71ee3$0fe71380$36158351@cr3lt><004a01c71f70$342533c0$5f057ad5@cr3lt> Message-ID: <010001c71fa9$ce236a30$5f057ad5@cr3lt> ooohh.. when I saw the subject, I fully expected a worked out proposal for extensible syntax in Haskell, just in time for Christmas. well, maybe next year!-) > It was to late when i realized that <= is already used as "smaller than > or equal to" :) oops. okay, lets change that. what about this: pattern =< expr ~~> pattern <- return expr a cleaner variant would be a let!, perhaps, but that would probably be too noisy for pattern guards? (also, we don't want to steal nice infix ops like <==) > do-notation is not the natural style for MonadPlus Maybe, the natural > style is more like the current syntax of pattern guards. I mean that one > rarely hides a Just constructor like in oh? getting rid of nested (case x of {Just this ->..; Nothing -> that}) is a very good argument in favour of do-notation for Maybe, and I find that very natural (for some definition of nature;-). granted, once one has taken that step, one is close to writing in monadic style anyway, so it is no longer specific which constructors are hidden. but I don't see a specific problem with Maybe there, and I haven't seen convincing sugar for MonadPlus yet. > general syntax is too much for the special case. But there is something > more canonical than completely disjoint syntax: in a sense, Claus' > suggestions are about making the syntax for the special case a *subset* > of the syntax for the more general one. indeed. thanks for pointing that out. I first went the other direction, but as you say, generalizing pattern guards introduces too much syntax in an awkward place. so my current suggestion follows the subset idea. > Some "higher order syntactic sugar" melting machine bringing all these > candies together would be very cool. hooray for extensional syntax!-) syntax pre-transformation that would allow me to extend a Haskell parser in library code is something I'd really like to see for Haskell, possibly combined with error message post-transformation. together, they'd smooth over the main objections against embedded DSLs, or allow testing small extensions of Haskell. I have been wondering in the past why I do not use Template Haskell more, given that I'm a great fan of meta-programming and reflection, and I think the answer is that it sits in an unfortunate way between two chairs: it cannot quite be used for syntax extensions because it insists on Haskell syntax/scopes/types, and it cannot quite be used as a frontend because there's some typing coming after it. persistent users have found wonderful things to do with it nevertheless, even analysis/ frontend stuff, but its main use seems to be program-dependent program generation, within the limits of Haskell syntax. in fact, I have a pragmatic need for even more, namely type system extensions as well: somewhere on my disk, I have a type-directed monadification prototype, based on a type system that infers not just a type, but a type coercion; works well, at least for simple monomorphic code, but what do I do with it? being type-directed, it uses a completely different foundation than the rest of HaRe refactorings, and to fully realize it for Haskell, I'd have to implement and -here comes the killer- maintain a complete Haskell type system, just because I need a few modifications/extensions. it is just not practical to do so, let alone once for every type-directed algorithm. Claus From gale at sefer.org Thu Dec 14 13:56:48 2006 From: gale at sefer.org (Yitzchak Gale) Date: Thu Dec 14 13:54:18 2006 Subject: "Higher order syntactic sugar" In-Reply-To: <010001c71fa9$ce236a30$5f057ad5@cr3lt> References: <20061211000619.GA8058@manthe.gotdns.org> <2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com> <2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com> <2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com> <5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> <01fc01c71ee3$0fe71380$36158351@cr3lt> <004a01c71f70$342533c0$5f057ad5@cr3lt> <010001c71fa9$ce236a30$5f057ad5@cr3lt> Message-ID: <2608b8a80612141056w5980181cuf296cabe1948109f@mail.gmail.com> >> ... <= is already used as "smaller than >> or equal to" :) > ...what about this: pattern =< expr > ... let!, perhaps, but that would probably be too > noisy for pattern guards? (also, we don't want to steal nice infix ops like <==) I had suggested <<- I wouldn't mind <-- or <== or the like. I think any of these better suggest "similiarity to <- yet different". (<= would have been perfect. Humph! They beat us to it.) -Yitz From apfelmus at quantentunnel.de Sun Dec 17 08:47:15 2006 From: apfelmus at quantentunnel.de (apfelmus@quantentunnel.de) Date: Sun Dec 17 08:47:22 2006 Subject: "Higher order syntactic sugar" In-Reply-To: <010001c71fa9$ce236a30$5f057ad5@cr3lt> References: <20061211000619.GA8058@manthe.gotdns.org><20061211000448.GA22250@cse.unsw.EDU.AU><2608b8a80612130309x76f3301ep484868d405d98c07@mail.gmail.com><2608b8a80612130323o6a9999bbq209a63f57358a042@mail.gmail.com><2608b8a80612130545j67be9907uf2457b2a226dacd3@mail.gmail.com><5ab17e790612130933g4bf58d5elb3362976fd516ac3@mail.gmail.com> <01fc01c71ee3$0fe71380$36158351@cr3lt><004a01c71f70$342533c0$5f057ad5@cr3lt> <010001c71fa9$ce236a30$5f057ad5@cr3lt> Message-ID: Claus Reinke wrote: > ooohh.. when I saw the subject, I fully expected a worked out proposal for > extensible syntax in Haskell, just in time for Christmas. well, maybe > next year!-) I'm sorry :( But this is because Santa Claus is not yet interested in Haskell: he swears on C-- for writing his high performance "real world" applications used in his Christmas gift delivery company. ;) >> I mean that one rarely hides a Just constructor like in > > oh? getting rid of nested (case x of {Just this ->..; Nothing -> that}) > is a very good argument in favour of do-notation for Maybe, and I find that > very natural (for some definition of nature;-). Ah, I meant it in the sense that Just and Nothing are very special constructors but that this behavior is wanted for other constructors too: data Color a b = Red a | Green a a | Blue b instance MonadPlus (Color a) where ... But now, we are tied again to a specific set of constructors. One might want to have fall-back semantics for any constructor at hand and that's what can be achieved with the "lifted let" (<- return, <<-, <--, <==, let', ...): (Red r <-- x, Left y <-- r, ... ) -- fall-back if anything fails `mplus` (Green g g' <-- x, Just k <-- g, ...) If one wants to hide these things with <- like in the case of Maybe, one would have to project into Maybe: fromRed (Red r) = Just r fromRed _ = Nothing fromBlue (Blue b) = Just b fromBlue _ = Nothing fromGreen (Green g g') = Just (g,g') fromGreen _ = Nothing fromLeft (Left x) = Just x fromLeft _ = Nothing (do r <- fromRed x y <- fromLeft r ...) `mplus` (do (g,g') <- fromGreen x k <- g ...) In this sense, the "lifted let" is more natural for fall-back because it treats all constructors as equal. Maybe just provides the semantics and is to be fused away. So I think that while do-notation is more natural than case-matching for Maybe, the most natural notation for the fall-back semantics are pattern guards. Likewise, list comprehension is the most natural style for (MonadPlus []). Here, one has normal <-, but boolean guards are sugared. >> Some "higher order syntactic sugar" melting machine bringing all these >> candies together would be very cool. > > hooray for extensional syntax!-) syntax pre-transformation that would > allow me to extend a Haskell parser in library code is something I'd > really like to see for Haskell, possibly combined with error message > post-transformation. together, they'd smooth over the main objections > against embedded DSLs, or allow testing small extensions of Haskell. Yes, that would be great. But I fear that this will result in dozens of different "Haskell" incarnations, one more obscure than the other. And its completely unclear how different syntax alterations would interoperate with each other. > I have been wondering in the past why I do not use Template Haskell > more, [...]but its main use seems to be program-dependent > program generation, within the limits of Haskell syntax. True. Compared to Template Haskell, a preprocessor allows syntactic extensions but is weak at type correctness. Regards, apfelmus From simonmar at microsoft.com Wed Dec 20 06:26:17 2006 From: simonmar at microsoft.com (Simon Marlow) Date: Wed Dec 20 06:23:44 2006 Subject: New Layout Rule take 2 In-Reply-To: <20061210045209.GJ8493@momenergy.repetae.net> Message-ID: haskell-prime-bounces@haskell.org wrote: > I have made some improvements to the algorithm, and I am happy to say > that with some minor tweaks, it correctly lays out the programs in > the nofib suite. > > the algorithm is not much more complicated than the current one in the > report, but doesn't have the parse-error rule. it does > require a single > token of lookahead to look for an "in". > > darcs get http://repetae.net/repos/getlaid/ > > I have also added a mode so it can work as a ghc preprocesor, allowing > very easy testing. just compile with. > > ghc -pgmF /path/to/getlaid -F --make Main.hs > > and it will automatically process all your files. Nice! I ran the GHC parser tests using your preprocessor, and get 9 failures out of 27 in the should_compile class. Some of these are bogus (problems with the lexer you're using rather than the layout preprocessor). The should_fail class all failed, but that's because column numbers are different in the preprocessed result, so the error messages changed, I'll need to look at these individually. I've attached a patch that corrects a couple of the failures in the should_compile class. Cheers, Simon -------------- next part -------------- A non-text attachment was scrubbed... Name: simonmar.patches Type: application/octet-stream Size: 1649 bytes Desc: simonmar.patches Url : http://www.haskell.org/pipermail/haskell-prime/attachments/20061220/d452202e/simonmar.obj