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

Pipeline following certain matches with cases on new lines does not depend on indentation #12422

Closed
LyndonGingerich opened this issue Nov 18, 2021 · 6 comments
Labels

Comments

@LyndonGingerich
Copy link

LyndonGingerich commented Nov 18, 2021

When I continue piping at the proper level of indentation after a match expression with case results specified on separate lines, the compiler sometimes apparently interprets my following code as applying to the last case of the match rather than to the whole.

This example function

let foo a =
  match a with
  | true ->
    (+)
  | false ->
    (-)
  <| 1

is apparently equivalent to

let foo a =
  match a with
  | true -> (+)
  | false -> (-) <| 1

rather than to

let foo a =
  (match a with
   | true ->
     (+)
   | false ->
     (-))
  <| 1

Expected behavior

val foo: bool -> int -> int with the returned value incremented by one if the bool argument is true or decremented by one otherwise.

Actual behavior

The (-) function shows this compiler error: The type ''a -> 'b' does not match the type 'int'. Further, foo appears neither to have a type signature nor to be defined thereafter in the code.

I would expect this behavior had I indented the last line differently:

let foo a =
  match a with
  | true ->
    (+)
  | false ->
    (-)
    <| 1

Known workarounds

Add the code following the expression to each case individually.

@LyndonGingerich LyndonGingerich changed the title Pipeline following certain matches or functions with cases on new lines does not depend on indentation Pipeline following certain matches with cases on new lines does not depend on indentation Nov 18, 2021
@dsyme
Copy link
Contributor

dsyme commented Nov 18, 2021

This is actually by design as things stand - it's related to the processing of infix operators and some leeway that is given for those.

There is an open design suggestion to give a warning for this, see fsharp/fslang-suggestions#806

My recommendation would be to use 4-space indentation (which is really recommended anyway) as it is very difficult to trigger this if you do

I also don't recommend the use of <| like this. Simply write the code differently.

@dsyme dsyme closed this as completed Nov 18, 2021
@LyndonGingerich
Copy link
Author

This is actually by design as things stand - it's related to the processing of infix operators and some leeway that is given for those.

Thank you for the information! For future reference, where could I have checked to find that this wasn't a bug?

@dsyme
Copy link
Contributor

dsyme commented Nov 18, 2021

Thank you for the information! For future reference, where could I have checked to find that this wasn't a bug?

IIRC the language specification does cover this but it's too detailed to follow

We should document this at https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/match-expressions and https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/conditional-expressions-if-then-else I guess. I'll put in an edit for this

@LyndonGingerich
Copy link
Author

For any future readers, I found an article that explains this rule.

@dsyme
Copy link
Contributor

dsyme commented Nov 18, 2021

Thanks, yes, we can reference that

@dsyme
Copy link
Contributor

dsyme commented Nov 18, 2021

I've made a note of this here: dotnet/docs#26813 and asked Scott Wlaschin if we can just lift his content across into docs.microsoft.com/dotnet/fsharp

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

2 participants