From the docs:
This attribute is used to indicate that references to the elements of a module, record or union type require explicit qualified access.
What is an explicit qualified access? What is an implicit access?
Maybe a concrete example would help.
The List
module has this attribute. This means you're not allowed to open the module:
open List // compile error!
map id [1;2]
Instead, you must do this:
List.map id [1;2]
From The About F# Page
Adding the
[<RequireQualifiedAccess>]
attribute to a module indicates that the module may not be opened and that references to the elements of the module require explicit qualified access. For example, the Microsoft.FSharp.Collections.List module has this attribute.This is useful when functions and values in the module have names that are likely to conflict with names in other modules and requiring qualified access can greatly increase the long-term maintainability and evolvability of a library: functions can be added to the module without breaking source compatibility.
The operator behaviour of F# lists, arrays, and sequences is manually mirrored between modules so that you can work with these structures in a consistent way. The implementations are different.
if you'd prefer to work in an implicit style, it's easy to set this up. Like if you are working predominantly with Lists, you could do this:
let inline map = List.map
etc.
Perhaps in the future, the kind of module will be inferred from the context (ie. we're working with a list, so obviously map refers to List.map). Ultimately, this is a language design question. What should the sensible default be? Defaults always creep into the broader code bases. On average, is this default more useful to programmers? Hence the RequireQualifiedAccess flag. Someone decided that this was the sensible way to do it. What's idiomatic? Does this still make sense?
The documentation you quote is not strictly true. The below is all implicit (I don't need to use a fully qualified explicit DicriminatedUnion.Case1, for example):
type DiscriminatedUnion =
| Case1
| Case2
| Case3
let f x =
match x with
| Case1 -> "case1"
| Case2 -> "case2"
| Case3 -> "case3"
f Case1
Excerpt from the book Expert F#
Some functional languages, such as Haskell, allow you to implicitly pass dictionaries of operations through an extension to type inference known as type classes. At the time of writing, this isn’t supported by F#, but the designers of F# have stated that they expect a future version of the language to support this. Either way, explicitly passing dictionaries of operations is common in all functional programming and is an important technique to master.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With