Skip to content

F# style guide concerning do! indents + docs issue #39302

Open
@palsskv

Description

@palsskv

Type of issue

Other (describe below)

Description

This ticket pertains to the F# code style guide and the linked documentation article.

The article says:

Here's an example with do! using two spaces of indentation (because with do! there is coincidentally no difference between the approaches when using four spaces of indentation):

// ✔️ OK
async {
  let! foo =
    fooBarBaz
    |> loremIpsumDolorSitAmet
    |> theQuickBrownFoxJumpedOverTheLazyDog

  do!
    fooBarBaz
    |> loremIpsumDolorSitAmet
    |> theQuickBrownFoxJumpedOverTheLazyDog
}
// ❌ Not OK - notice the "do!" expression is indented two spaces more than the `let!` expression
async {
  let! foo =
    fooBarBaz
    |> loremIpsumDolorSitAmet
    |> theQuickBrownFoxJumpedOverTheLazyDog
  do! fooBarBaz
      |> loremIpsumDolorSitAmet
      |> theQuickBrownFoxJumpedOverTheLazyDog
}

My comments:
There is a difference when using 4 spaces, because do! works out to be exactly 4 characters.
The "bad example" becomes aligned and takes up less space:

async {
    let! foo =
        fooBarBaz
        |> loremIpsumDolorSitAmet
        |> theQuickBrownFoxJumpedOverTheLazyDog
    do! fooBarBaz
        |> loremIpsumDolorSitAmet
        |> theQuickBrownFoxJumpedOverTheLazyDog
} |> ignore

I have encountered this issue when working with async and other CTES. The new lines inserted after do! don't affect alignment and reduce information density.

Here's an abbreviated version of some of my code. It's formatted by Fantomas with default settings.

// [...]
    match relatedParent with
    | Some parent ->
        do!
            writeRelated<TType1, TParent>
                httpClient
                host
                ctx
                siteId
                targetId
                (cast ctx)
                [| parent.Id |]
    | _ -> ()

    do!
        writeRelated<TType1, TType3>
            httpClient
            host
            "en"

    do!
        writeRelated<TType1, TType2>
            httpClient
            host
            "en"

    if someRelatedDataVals.Length > 0 then
        do!
            writeRelated<TType1, TType2>
                httpClient
                host
                "en"
                dataCxt
                siteId

    do!
        publish<TargetType> httpClient host "en" scope siteId targetId
        |> AsyncResult.ignore

Here's how the same code would look like with the change.

// [...]
    match relatedParent with
    | Some parent ->
        do! writeRelated<TType1, TParent>
                httpClient
                host
                ctx
                siteId
                targetId
                (cast ctx)
                [| parent.Id |]
    | _ -> ()

    do! writeRelated<TType1, TType3>
            httpClient
            host
            "en"

    do! writeRelated<TType1, TType2>
            httpClient
            host
            "en"

    if someRelatedDataVals.Length > 0 then
        do! writeRelated<TType1, TType2>
                httpClient
                host
                "en"
                dataCxt
                siteId

    do! publish<TargetType> httpClient host "en" scope siteId targetId
        |> AsyncResult.ignore

Page URL

https://learn.microsoft.com/en-us/dotnet/fsharp/style-guide/formatting

Content source URL

https://github.com/dotnet/docs/blob/main/docs/fsharp/style-guide/formatting.md

Document Version Independent Id

1efdd523-8552-6421-e149-74f76826ef8f

Article author

@KathleenDollard

Metadata

  • ID: 8c09996f-24ac-cf39-ef43-d7909cbc2b89
  • Service: dotnet-fsharp

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions