xneg
xneg

Reputation: 1368

Type name as identifier in F#

I just started to study F# and accidentally wrote this binding

let List = 1

Now when I try to obtain List methods such as 'filter' I get this error

error FS0039: The field, constructor or member 'filter' is not defined.

Of course using method with full type name like Microsoft.FSharp.Collections.List.filter is still working.

I'm wondering why it is possible to use type name as identifier in F# and how I can set back name List to type List from Microsoft.FSharp.Collections.

When I tried to reassign like this

type List = Microsoft.FSharp.Collections.List<'T>

I get

Error FS0039: The type parameter 'T is not defined.

Thank you!

Upvotes: 3

Views: 434

Answers (2)

Tomas Petricek
Tomas Petricek

Reputation: 243096

You should just rename your let binding from List to something sensible - as Gustavo mentioned, your definition is shadowing the core List module from F# and there is no way to use List to refer both to your integer and to the module. Shadowing core functions will make your code pretty confusing. It's also a good idea to use camelCase for let bindings, but that's a matter of taste.

If you insist on shadowing List, then you won't be able to call List.filter using List.filter. If you wanted something shorter, you could define module alias:

module FsList = Microsoft.FSharp.Collections.List

Note that your attempt to do something similar with List<'T> does not do the same thing, because functions such as filter are in a module named List rather than being static members of the type. With this, you can call filter using FsList.filter.

Upvotes: 4

Gus
Gus

Reputation: 26204

In F# you can redefine almost everything and shadow existing definitions. This applies to both types (well actually types have a different behavior regarding shadowing, they shadow their values as you open the namespaces) and values but not interchangeably since values and type (and also modules) can somehow coexist at the same time in the scope. The compiler will do his best to find out which one is.

You are not forced to, but it's a common good practice in F# not to use let bindings in uppercase.

Regarding your second question, you are using a type parameter in the right side which doesn't exist in the left side of the assignment, it should be:

type List<'T> = Microsoft.FSharp.Collections.List<'T>

But notice that filter doesn't belong to the type. It's rather defined in the List module.

Upvotes: 6

Related Questions