Is there any difference between List<int>
and int list
?
For example, when I write a function
let somefn a : int list = a
and
let somefn2 a : List<int> = a
Returned value types differ with notation style, and even in the console output, when I invoke those functions, it shows two distinctly noted types
val it : int list = ...
and
val it : List<int> = ...
Although, logic and idea seems to be same, Interpreter/compiler interprets those two types in a different way.
Is there any difference?
To expand slightly on John Palmer's correct answer, here's an F# Interactive session that illustrates how int list
and List<int>
are synonyms, right up until the moment when they aren't. And note how there's also list<int>
and ResizeArray<int>
for extra confusion:
F# Interactive for F# 4.0 (Open Source Edition)
Freely distributed under the Apache 2.0 Open Source License
For help type #help;;
> typeof<list<int>>.Namespace ;;
val it : string = "Microsoft.FSharp.Collections"
> typeof<list<int>>.Name ;;
val it : string = "FSharpList`1"
> typeof<List<int>>.Namespace ;;
val it : string = "Microsoft.FSharp.Collections"
> typeof<List<int>>.Name ;;
val it : string = "FSharpList`1"
> typeof<int list>.Namespace ;;
val it : string = "Microsoft.FSharp.Collections"
> typeof<int list>.Name ;;
val it : string = "FSharpList`1"
> typeof<ResizeArray<int>>.Namespace ;;
val it : string = "System.Collections.Generic"
> typeof<ResizeArray<int>>.Name ;;
val it : string = "List`1"
-
- printfn "Now we'll open System.Collections.Generic. Watch what happens."
- ;;
Now we'll open System.Collections.Generic. Watch what happens.
val it : unit = ()
> open System.Collections.Generic ;;
> typeof<list<int>>.Namespace ;;
val it : string = "Microsoft.FSharp.Collections"
> typeof<list<int>>.Name ;;
val it : string = "FSharpList`1"
> typeof<List<int>>.Namespace ;;
val it : string = "System.Collections.Generic"
> typeof<List<int>>.Name ;;
val it : string = "List`1"
> typeof<int list>.Namespace ;;
val it : string = "Microsoft.FSharp.Collections"
> typeof<int list>.Name ;;
val it : string = "FSharpList`1"
> typeof<ResizeArray<int>>.Namespace ;;
val it : string = "System.Collections.Generic"
> typeof<ResizeArray<int>>.Name ;;
val it : string = "List`1"
So List<int>
with an uppercase L will be the F# list type (an immutable linked list with a head pointer, which has O(1) head access and prepending, but O(N) tail access and appending) if you haven't opened the System.Collections.Generic
namespace. But if you have, then suddenly List<int>
resolves to the .Net System.Collections.Generic.List<T>
class, which is a mutable data structure with O(1) lookups anywhere, amortized O(1) appends, but O(N) prepends. So it really matters which one you're using.
To be on the safe side, if you intend to use the F# list structure, I'd write it as either int list
(my preference since it reads like English) or list<int>
(which some people prefer since it reads like C#). Neither of those will suddenly acquire a different meaning when you open a .Net namespace; they will continue to refer to the F# list structure. And avoid using List<int>
to refer to F# lists; only use that when you have opened the System.Collections.Generic
namespace and you intend to get a .Net System.Collections.Generic.List<T>
instance. Finally, note that in F#, System.Collections.Generic.List<T>
has a type alias available without opening the System.Collections.Generic
namespace. By default, without needing to open any namespaces, you can access this type under the name ResizeArray<T>
.
Summary:
Safe type names:
int list
and list<int>
(always refer to the F# singly-linked list type)ResizeArray<int>
(always refers to the C# System.Collections.Generic.List<T>
type)Unsafe type names because their meaning changes depending on what namespace you've opened:
List<int>
(refers to the F# singly-linked list type at first, but changes meaning to the C# type if you open the System.Collections.Generic
namespace). As a general rule, don't use this type name; if you want this type in F#, use ResizeArray<int>
instead.There is no difference, there is a type alias.
Except under one case, where you have run
open System.Collections.Generic
Which has its own list type
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