Skip to content

Allow attributes after the module keyword #757

@Happypig375

Description

@Happypig375

RFC https://github.com/fsharp/fslang-design/blob/main/preview/FS-1107-Allow-attributes-after-the-module-keyword.md

Allow attributes after the module keyword

Consider:

[<AutoOpen>]
module M =
    [<AbstractClass>]
    type C() = class end
    [<Literal>]
    let X = 3

The Literal attribute can be embedded into the let:

[<AutoOpen>]
module M =
    [<AbstractClass>]
    type C() = class end
    let [<Literal>] X = 3 // ✓

Same for the AbstractClass:

[<AutoOpen>]
module M =
    type [<AbstractClass>] C() = class end // ✓
    let [<Literal>] X = 3

But not the AutoOpen.

module [<AutoOpen>] M = // FS0010: Unexpected start of structured construct in definition. Expected identifier, 'global' or other token.
    type [<AbstractClass>] C() = class end // FS0010: Unexpected keyword 'type' in implementation file
    let [<Literal>] X = 3

The existing way of approaching this problem in F# is leaving the AutoOpen above the module.

Pros and Cons

The advantages of making this adjustment to F# are

  1. Consistency - modules are just specialized types, so placing attributes after the keyword should be allowed as well.
  2. Conciseness - we can utilize the horizontal space to our advantage, thus scrolling less.

The disadvantage of making this adjustment to F# is having more ways to do the same thing. However, precedence has been already made for types and lets.

Extra information

Estimated cost (XS, S, M, L, XL, XXL): S

Related suggestions:
#33
I would say that this should be allowed for members as well.

// Not using a module to ensure that the module suffix is not added
type MyList() =
    // Fields omitted
    [<CompiledName("Map")>]
    static member map f l =
        // Implementation omitted

Thanks for the suggestion
However I will decline this: what we have works, and the proposed saving is only one line, and the lines become loooong. In balance I don't see a net benefit.

Sure, what we have works, but inconsistent language features are worse than having multiple ways to do the same thing. (Recall: Unification of List, Array, Seq functions in F# 4.0)

Whether the lines become long depends on the length of the name of members and attributes. If they are short enough, they deserve to be combined to utilize more horizontal space.

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.
    (This has sort of been decided for members, but not modules. Module definitions tend to be much shorter than member definitions anyways.)

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions