List <int> vs int list

时间:2016-12-12 00:55:29

标签: list generics f#

List<int>int list之间有什么区别吗? 例如,当我写一个函数

let somefn a : int list = a

let somefn2 a : List<int> = a

返回值类型因符号样式而异,甚至在控制台输出中,当我调用这些函数时,它会显示两种明显的类型

val it : int list = ...

val it : List<int> = ...

虽然逻辑和想法似乎相同,但解释器/编译器以不同的方式解释这两种类型。

有什么不同吗?

3 个答案:

答案 0 :(得分:17)

要稍微扩展John Palmer的正确答案,这里是一个F#互动会话,说明int listList<int>是同义词的方式,直到它们不是。并注意如果还有list<int>ResizeArray<int>的额外混淆:

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"

所以带有大写L的List<int>将是F#列表类型(带有头指针的不可变链表,其具有O(1)头访问和前置,但O(N)尾访问和追加)如果您尚未打开System.Collections.Generic命名空间。但是,如果你拥有,那么突然List<int>解析为.Net System.Collections.Generic.List<T>类,这是一个带有O(1)查找的可变数据结构在任何地方,摊销O(1)追加,但O(N)预先。所以它真的很重要你正在使用哪一个。

为了安全起见,如果您打算使用F#列表结构,我会将其写为int list(我的偏好,因为它读起来像英语)或list<int>(其中一些)人们更喜欢,因为它读起来像C#)。当你打开.Net命名空间时,这些都不会突然获得不同的含义;他们将继续参考F#列表结构。并避免使用List<int>来引用F#列表;只有在打开System.Collections.Generic命名空间并且打算获得.Net System.Collections.Generic.List<T>实例时才使用它。最后请注意,在F#中,System.Collections.Generic.List<T>有一个类型别名,而不会打开System.Collections.Generic命名空间。默认情况下,无需打开任何名称空间,您可以使用名称ResizeArray<T>

访问此类型

要点:

安全类型名称

  • int listlist<int>(始终引用F#单链接列表类型)
  • ResizeArray<int>(始终指C#System.Collections.Generic.List<T>类型)

不安全的类型名称,因为它们的含义会根据您打开的名称空间而改变:

  • List<int>(首先是指F#单链接列表类型,但如果打开System.Collections.Generic命名空间,会将更改为C#类型)。作为一般规则,请勿使用此类型名称;如果您想在F#中使用此类型,请改用ResizeArray<int>

答案 1 :(得分:8)

没有区别,有一个类型别名。

除了一个案例,你已经在哪里运行

 open System.Collections.Generic

哪个有自己的列表类型

答案 2 :(得分:3)

  • 通常,对于包含一个参数的通用类型,TypeParameter GenericType相当于GenericType<TypeParameter>

  • FSharp.Core中声明的F#immutable列表类型在范围内,默认情况下有两个名称:Listlist。它有一个类型参数,因此int listlist<int>int ListList<int>是等效的。

  • System.Collections.Generic有一个不同的List<'T>类型,它在F#中具有更合适的别名ResizeArray。如果您打开System.Collections.GenericList会引用此可变的数组换行类型。

为避免混淆,习惯上不使用List使用大写L来引用F#中的类型。相反,list使用小写l用于FP源,不可变,单链接列表,而ResizeArray用于引用OO样式的可变集合。大多数人还坚持使用不同的样式int listResizeArray<int>,并避免使用其他组合。

对于类型信息,IDE和类似信息有时会尝试以声明方式显示类型,因为通常有很多方法可以引用相同的类型。这并不意味着行为上的差异。