Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional Haskell/Elm style lambdas next to the existing syntax #1231

Closed
5 tasks done
ken-okabe opened this issue Jan 9, 2023 · 6 comments
Closed
5 tasks done

Optional Haskell/Elm style lambdas next to the existing syntax #1231

ken-okabe opened this issue Jan 9, 2023 · 6 comments
Labels

Comments

@ken-okabe
Copy link

ken-okabe commented Jan 9, 2023

I propose Optional Haskell/Elm style lambdas next to the existing syntax.

The existing way of approaching this problem in F# is Lambda Expressions: The fun Keyword (F#)

fun x -> x + 1
fun a b c -> printfn "%A %A %A" a b c
fun (a: int) (b: int) (c: int) -> a + b * c
fun x y -> let swap (a, b) = (b, a) in swap (x, y)

We can rewrite

let f = fun a b c -> a + b + c

to

let f' = fun a -> fun b -> fun c -> a + b + c

image

The latter corresponds to the type definition: int -> int -> int -> int well; however, the fun_ (_ means SPACE) keyword looks redundant/verbose.


Note: \ is from λ (lambda)

Simply replacing the code text with fun_ to \,

image
The code becomes much more concise and corresponds to the type annotation well.
Typing amount and readability imporves.

Interestingly enough, the code above corresponds to the syntax for lambda expression in Haskell and Elm pretty well.
https://wiki.haskell.org/Anonymous_function
https://elm-lang.org/docs/syntax#functions

Background

Implicit style lambda

we treat the first x as the "argument", "parameter" or "placeholder" implicitly

Explicit style lambda

the "argument", "parameter" or "placeholder" is explicitly defined with \ or fun_ keyword

  • \x -> x + 1 (Haskell, Elm)
  • fun x -> x + 1 (OCaml, F#)

The explicit style used in Haskell/Elm and F# is identical and just syntax letter is different and replaceable.

Make the fun keyword optional #168

Make the fun optional. Otherwise, it is more verbose than C#.

The status is approved-in-principle

Actually, the difference between Implicit style and Explicit style is not trivial at all.

Some informative comments in the thread are:
Haskell like
abelbraaksma commented on Nov 23, 2020

I don't think it's possible to get rid of fun without introducing ambiguities.

abelbraaksma commented on Nov 23, 2020

consider current code:

let f x y = fun z -> x >> fun y -> z >> y

Then, let's ditch the fun:

let f x y = z -> x >> y -> z >> y

What is y? In the first example, y is out of scope and basically a dummy param. In the second example, it isn't (or at the very least, it appears it isn't). Furthermore, one could argue that the second example has unclear operator precedence rules (though that could be covered in the parser, surely).

abelbraaksma commented on Nov 23, 2020

The other issue is the scoping, as mentioned. fun introduces the scope and is fundamental in that. The first two examples above have unclear scope after dropping fun.

dsyme commented on Oct 28, 2022

dsyme commented on Oct 28, 2022

if you want complex patterns you use the existing fun, and function when you want multiple cases.

I'm pretty sure the primary developer works hard, but currently no one established the RFC, and so far, it seems that the consequence of the optional fun keyword is that usage of fun keyword is necessary in some complicated cases.

#168 is the mixed style of lambda expression; Maybe, it's possible to write lambda expressions without fun in any complicated cases, but as long as I've read, no one is so sure.

This is a very complicated approach and probably will end up with having both Implicit style most of the time, then Explicit style sometimes.

On the other hand, \x -> … is always Explicit style.
Sure you have 2 ways to write the identical mathematical instance/identical lambda expression in fun_ or \, but this is a much simpler approach.

image

will become to

image

or

image

as shown above, in complicated lambda expressions, explicitly defining which are arguments/parameters with \ prefix or fun_ keyword keeps the expression structure clear and readable, so it is not trivial at all.

At the outermost, there are 2 kinds of people.

A) We like fun syntax and don't feel it's redundant or verbose, so keep it.

B) We don't like fun syntax and feel it's redundant and verbose, remove it.

In B type, there are 2 kinds of people.

B1) Removing fun is Good, but replacing it to \ prefix is NG, then it's good for us to have C# like lambda style in F#. (Implicit style advocator) Having another syntax for the identical code is bad practice even it's concise and wanted. The complicated approach is justified by this principle.

B2) Removing fun is Good, and replacing it to \ prefix, then it's good for us to have Haskell-like lambda style in F#. (Explicit style advocator) It is totally fine to have a shorter concise syntax next to the existing syntax. Compared to the simple rule and clear readability, the complicated approach does not look like a smart move. Having the option to write in shorter/concise syntax is much better than keep using fun sometimes when it would be needed in complicated situations. After all, we would like to avoid using mixed style lambda in my code. It's not like denying their effort but just give us the third option. It's easy to implement anyway.

Pros and Cons

Pros

The advantages of making this adjustment to F# are ...

  • It's wanted and does the job - Short syntax/concise and improves readability to solve the problem (an alternative option for redundant/verbose fun_ syntax)
  • "new shorter syntax to do the same thing" actually means this is the problem solver
  • Don't have to write fun even in the most complicated case
  • Preserves the ML nature for Explicit style lambda and won't break anything
  • Proven and rock solid in Haskell
  • Simple approach
  • Extremely easy to implement (the keyword difference) without hard work

Rickasaurus commented on Jul 22, 2017 20 upvotes

We don't currently use \ to mean anything, so why not gift it from haskell if fun is too much?

benjamin-thomas commented on Nov 4, 2022

I've stumbled upon this thread because I'm learning F# and was looking for a shortcut to define lambdas.
IMO, you should consider having the backslash sign \ (which is lambda-looking) synonymous to fun. This is what Haskell and Elm do. Considering these languages share quite a few idioms/constructs with F#, I feel it makes sens to make a note of it.

Cons

The disadvantages of making this adjustment to F# are ...

  • This will add new syntax to do the same thing

TIHan commented on Nov 27, 2017

IMHO, we shouldn't add more ways to do the same thing in this regard. You will not gain that much from trying to shorten syntax; only lead to more inconsitent code across large projects. The property accessor from the other issue is kinda ok, but even then even that can lead to more inconsistencies of just doing the same thing.

(the comment seems to be written against #168)

abelbraaksma commented 16 hours ago

In the end, you pick one, and stick with it. None of these languages mix two styles, some have optionality for keywords though, as also proposed here.

  • There are people who don't like Haskell like syntax much and do not want to allow this, and they only prefer C# like syntax for beginner's reach.

  • The same people tend to deny the improvement of readability.

  • The main developer probably does not like it

dsyme commented on Nov 16, 2017

I'm pretty much against the use of \ in operators. Every language I've seen using \ gets harder to read.
I will close this as we decided not to do this in F# 1.x for readability concerns.

Extra information

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

For Readers

If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.

@abelbraaksma
Copy link
Member

abelbraaksma commented Jan 9, 2023

  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken

Should be ‘unchecked’. As discussed in the other thread, this is the main problem with this idea. We typically don’t introduce new syntax for something that already has syntax. There may be exceptions, but it’ll need a very strong use case.

I know you submitted this because in the linked thread there’s an old comment describing this, that got 20 upvotes and zero downvotes, and we floated the idea of what the community would thin about it now.

Re ‘implicit’: we usually use that word for something that’s truly implicit (like implicit type conversions), having -> in the syntax, as from the linked proposal, makes it explicit: if there’s a thin arrow, there’s a function. I understand that it may feel ‘implicit’, but in the end it’s just as explicit as everything else in the syntax.

(fwiw, I don’t really know a better alternative term, but just wanted to stress this point)

Estimated cost for #168 : XL or XXL

I’m not sure about that. If it can be done in lexing/parsing, where the change belongs, it may be much, much simpler than we think. But let’s try to keep these discussions separate, it’s good that you split it up. This one is about proposing new syntax \x.

@vzarytovskii
Copy link

I have removed the estimated cost for the other one (making fun optional), as it's orthogonal to this suggestion

@dsyme
Copy link
Collaborator

dsyme commented Jan 9, 2023

I agree this has already been decided - we won't be introducing new syntax - tbh removing the fun is really the only design path to explore.

@dsyme dsyme closed this as completed Jan 9, 2023
@dsyme dsyme added the declined label Jan 9, 2023
@ken-okabe
Copy link
Author

ken-okabe commented Jan 9, 2023

We typically don’t introduce new syntax for something that already has syntax. There may be exceptions, but it’ll need a very strong use case.

Exactly. This is the one, that I thought.
An alternative syntax for redundant/verbose fun_ syntax. If the length of the syntax itself is the problem, that should be a very strong use case.

I understand that it may feel ‘implicit’, but in the end it’s just as explicit as everything else in the syntax.

Perhaps you are right.

I agree this has already been decided - we won't be introducing new syntax - tbh removing the fun is really the only design path to explore.

Fine with me, if everything is considered, I'm just looking forward to having the removing the fun path. Thanks for your work.

@voronoipotato
Copy link

voronoipotato commented Jan 11, 2023

Commenting so that people looking at this know what to do. Use prettify-symbols-mode or a ligature to convert it to λ (vscode) and add yourself a shortcut for typing "fun". There's even a reference to F# in the extension. You may need to fix/fork the vscode extension, but it works well on emacs.

@ken-okabe
Copy link
Author

Must mention your Feature request: prettify symbols mode microsoft/vscode#171074

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants