Sugar for function application

Hello cafe, I have just had a discussion on #haskell about whether it would be useful to have syntactic sugar for exception handling. This and syntactic sugar in general is a very controversial topic, seeing that 'do' notation is used a lot, where applicative/combinator style would be more appropriate. Some people would call this "abuse". Let me tell you why I would like syntactic sugar, first. Haskell is in many regards very beautiful and the layout of code expresses its structure. However, when it comes to exception handling I have two options: use either parentheses or infix operator style. For my taste both get ugly, as soon as you have more than just an action and its small exception handler. At some point you end up using 'let' and/or 'where' to introduce extra names, something which you would want to avoid in general, unless it really adds value to your code. Currently you introduce names just to make the code look nicer. I find this very unfortunate. However, because it is such a controversial topic whether or not to add syntactic sugar for exceptions, I'm proposing an alternative, which seems to be nicer, because it doesn't introduce extra syntax for specific things (like exceptions) and even has the potential to get rid of some keywords (most notably 'if', 'then' and 'else') without making code look worse: layout-style syntactic sugar for function application. Here is an example of what it might look like: function $$ anArgument sin (x^2) anotherArgument f $ x + 3 printf $$ "%s: %s" key values ! key -- Assuming that 'if' is just a function: -- if :: Bool -> a -> a -> a if $$ even x x^2 (x - 1)^2 catch $$ do someOperation someOtherOperation yetAnotherOperation \exception -> putStrLn "Error:" >> print exception bracket $$ openFile "blah" ReadMode \h -> hClose h >> putStrLn "File closed." \h -> do putStrLn "File opened." doSomethingWithHandle h Instead of the symbolic ($$) I could also think of 'with' or 'of' as appropriate keywords, although 'of' would be ambiguous: catch with do someOperation someOtherOperation yetAnotherOperation \exception -> putStrLn "Error:" >> print exception Also you should be able to use do-style semicolons: printf with "%s: %s"; key; values ! key What do you think? I would love to see this '$$' or 'with' construct as a GHC extension. Greets Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/

On Mar 23, 2010, at 13:39 , Ertugrul Soeylemez wrote:
code look worse: layout-style syntactic sugar for function application. Here is an example of what it might look like:
function $$ anArgument sin (x^2) anotherArgument f $ x + 3
Doesn't layout already do this? function arg1 arg2 arg3 -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On Tue, 2010-03-23 at 22:23 -0400, Brandon S. Allbery KF8NH wrote:
On Mar 23, 2010, at 13:39 , Ertugrul Soeylemez wrote:
code look worse: layout-style syntactic sugar for function application. Here is an example of what it might look like:
function $$ anArgument sin (x^2) anotherArgument f $ x + 3
Doesn't layout already do this?
function arg1 arg2 arg3
As I understend function $$ sin x y z is function (sin x) (y) function sin x y z is function (sin) (x) (y) (z) function $ sin x y z is function (sin (x) (y) (z)) Regards

Brandon S. Allbery KF8NH wrote:
On Mar 23, 2010, at 13:39 , Ertugrul Soeylemez wrote:
layout-style syntactic sugar for function application. Here is an example of what it might look like:
function $$ anArgument sin (x^2) anotherArgument f $ x + 3
Doesn't layout already do this?
function arg1 arg2 arg3
The layout rule is only triggered by a limited set of keywords (like do, where, let, ...), and Ertugrul's proposal is to add a keyword for function applicaton to this set. I like this idea, because it would enable non-monadic embedded DSLs to use layout. For example, consider setting properties in wxHaskell: layoutSet myButton $$ text := "Ok" on action := doSomething instead of set myButton [ text := "Ok" , on action := doSomething ] Of course, this would need some type hackery à la PrintF to make set accept multiple arguments, and the proliferation of such type hackery may seem unfortunate. On the other hand, the hackery could possibly be encapsulated in a combinator like polyvariadic :: Poly a b c => ([a] -> b) -> c so that layoutSet can be implemented as layoutSet widget = polyvariadic (set widget). Tillmann

Tillmann Rendel wrote:
I like this idea, because it would enable non-monadic embedded DSLs to use layout.
For example, consider setting properties in wxHaskell:
layoutSet myButton $$ text := "Ok" on action := doSomething
You can abuse do notation to achieve that, by wrapping the list in a suitable Writer monad layoutSet myButton $ do text &= "Ok" on action &= doSomething with (&=) :: Property a -> a -> Writer Properties () It's ugly semantically but pleasant syntactically. Regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

Tillmann Rendel
Of course, this would need some type hackery à la PrintF to make set accept multiple arguments, and the proliferation of such type hackery may seem unfortunate. On the other hand, the hackery could possibly be encapsulated in a combinator like
polyvariadic :: Poly a b c => ([a] -> b) -> c
so that layoutSet can be implemented as
layoutSet widget = polyvariadic (set widget).
I could think of a layout-based keyword to construct Alternative values, which wouldn't require type hackery. Something like this: acat a b c which would be equivalent to a <|> b <|> c Then you could write: layoutSet myButton $ acat [text := "Ok"] [on action := doSomething] Occasionally this would be very useful for parsers: numericWord = acat try $ 1 <$ string "one" try $ 2 <$ string "two" try $ 3 <$ string "three" This together with layout-based function application could be great syntactical features. Firstly it would be strictly optional, so you could still program without or with less layout, if you prefer. Secondly you could get rid of a number of other keywords this way, most notably the 'if', 'then' and 'else' keywords. Some people like 'then' and 'else'. So instead of completely removing them, you can turn them into functions instead: newtype Then a = Then a newtype Else a = Else a if :: Bool -> Then a -> Else a -> a then :: a -> Then a else :: a -> Else a if condition $$ then thisIfTrue else thisIfFalse The benefit is that 'if', 'then' and 'else' aren't keywords anymore and can be used for other purposes in narrow scopes. Sometimes this would be useful. Greets Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/
participants (5)
-
Brandon S. Allbery KF8NH
-
Ertugrul Soeylemez
-
Heinrich Apfelmus
-
Maciej Piechotka
-
Tillmann Rendel