如何实例化一个'typed' Map?
How to instatiate a 'typed' Map?
我创建了一个自定义类型,它正在实现 Map
。
type School = Map<int, string list>
我现在尝试了各种方法来实例化该类型,但总是失败。
通过尝试 Nr.1,我想也许有人可以 'dot' class(不知何故)。
let xyz = School.Map.empty;;
or
let kgse = School.empty;;
//The type 'Map<Key,Value>' does not define the field, constructor or member 'empty'.
我希望第 2 次尝试 f# 知道我创建的映射是否与它自动分配的自定义类型具有相同的结构。
let xyz =
- Map.empty.
- Add(2, ["Alex"]);;
val xyz: Map<int,string list> = map [(2, ["Alex"])]
这有效,但仅 returns 一般 Map
class。
最后,我想也许我可以转换类型。
let xyz =
- School Map.empty.
- Add(2, ["Alex"]);;
这又给我一个错误:
Successive arguments should be separated by spaces or tupled, and arguments involving function or method applications should be parenthesized
.
向xyz
添加School
类型注释:
let xyz : School = Map.empty.Add(2, ["Alex"])
使用dotnet fsi
:
> type School = Map<int, string list>
-
- let xyz : School = Map.empty.Add(2, ["Alex"]);;
type School = Map<int,string list>
val xyz : School = map [(2, ["Alex"])]
您还可以创建 return School
的函数,然后按如下方式使用它们:
同样,在 dotnet fsi
中:
> let makeSchool s : School = Map.empty.Add s
-
- let addStudent (school: School) student : School = school.Add student
-
- let xyz' = makeSchool (3, ["Betty"])
-
- let newStudent = (4, ["Charles"])
-
- let schoolWithNewStudentAdded = addStudent xyz' newStudent
- ;;
val makeSchool : int * string list -> School
val addStudent : school:School -> int * string list -> School
val xyz' : School = map [(3, ["Betty"])]
val newStudent : int * string list = (4, ["Charles"])
val schoolWithNewStudentAdded : School =
map [(3, ["Betty"]); (4, ["Charles"])]
这里的部分问题是 School
,正如您所定义的,是一个 type abbreviation,而不是它自己的一个独特类型。这意味着它只是 Map<int, string list>
的另一个名称。这是一个很好的轻量级方法,并且仍然允许您创建自己的 School.empty
值,如果您愿意的话:
module School =
let empty : School = Map.empty
let xyz = School.empty.Add(2, ["Alex"])
另一方面,如果您确实希望 School
成为实数类型,则应考虑将其定义为记录或可区分联合:
type School =
private MkSchool of Map<int, string list> with
member this.Add(key, values) =
let (MkSchool map) = this
MkSchool (map.Add(key, values))
module School =
let empty = MkSchool Map.empty
let xyz = School.empty.Add(2, ["Alex"])
F# 具有非常简洁的功能 - 具有相同名称的类型可以相互扩展。例如 System.Collection.Generic
具有类型 EqualityComparer
和静态 属性 Default
,return 对于给定的泛型类型, 但 它不适合集合,因为它们将作为参考进行比较,而不是按值进行比较。
在 C# 中,您不能为静态 class 编写扩展来调用 EqualityComparer<T>.ForCollection
,但您可以使用 F#:
module EqualityComparer =
let ForCollection<'a> = ...
let def = EqaulityComparer.Default
let mine = EqualityComparer.ForCollection
如您所见,我们用 module
扩展了 static class
。这是 2 个具有相同名称的不同类型,我们可以使用两者的方法和属性。
Map
class和Map
模块也是如此。您已经为可以实例化的类型创建了别名,但还没有为辅助模块创建别名。您需要做的是为 module
创建类型缩写
type School = Map<int, string list>
module School = Map
School.empty
我创建了一个自定义类型,它正在实现 Map
。
type School = Map<int, string list>
我现在尝试了各种方法来实例化该类型,但总是失败。 通过尝试 Nr.1,我想也许有人可以 'dot' class(不知何故)。
let xyz = School.Map.empty;;
or
let kgse = School.empty;;
//The type 'Map<Key,Value>' does not define the field, constructor or member 'empty'.
我希望第 2 次尝试 f# 知道我创建的映射是否与它自动分配的自定义类型具有相同的结构。
let xyz =
- Map.empty.
- Add(2, ["Alex"]);;
val xyz: Map<int,string list> = map [(2, ["Alex"])]
这有效,但仅 returns 一般 Map
class。
最后,我想也许我可以转换类型。
let xyz =
- School Map.empty.
- Add(2, ["Alex"]);;
这又给我一个错误:
Successive arguments should be separated by spaces or tupled, and arguments involving function or method applications should be parenthesized
.
向xyz
添加School
类型注释:
let xyz : School = Map.empty.Add(2, ["Alex"])
使用dotnet fsi
:
> type School = Map<int, string list>
-
- let xyz : School = Map.empty.Add(2, ["Alex"]);;
type School = Map<int,string list>
val xyz : School = map [(2, ["Alex"])]
您还可以创建 return School
的函数,然后按如下方式使用它们:
同样,在 dotnet fsi
中:
> let makeSchool s : School = Map.empty.Add s
-
- let addStudent (school: School) student : School = school.Add student
-
- let xyz' = makeSchool (3, ["Betty"])
-
- let newStudent = (4, ["Charles"])
-
- let schoolWithNewStudentAdded = addStudent xyz' newStudent
- ;;
val makeSchool : int * string list -> School
val addStudent : school:School -> int * string list -> School
val xyz' : School = map [(3, ["Betty"])]
val newStudent : int * string list = (4, ["Charles"])
val schoolWithNewStudentAdded : School =
map [(3, ["Betty"]); (4, ["Charles"])]
这里的部分问题是 School
,正如您所定义的,是一个 type abbreviation,而不是它自己的一个独特类型。这意味着它只是 Map<int, string list>
的另一个名称。这是一个很好的轻量级方法,并且仍然允许您创建自己的 School.empty
值,如果您愿意的话:
module School =
let empty : School = Map.empty
let xyz = School.empty.Add(2, ["Alex"])
另一方面,如果您确实希望 School
成为实数类型,则应考虑将其定义为记录或可区分联合:
type School =
private MkSchool of Map<int, string list> with
member this.Add(key, values) =
let (MkSchool map) = this
MkSchool (map.Add(key, values))
module School =
let empty = MkSchool Map.empty
let xyz = School.empty.Add(2, ["Alex"])
F# 具有非常简洁的功能 - 具有相同名称的类型可以相互扩展。例如 System.Collection.Generic
具有类型 EqualityComparer
和静态 属性 Default
,return 对于给定的泛型类型, 但 它不适合集合,因为它们将作为参考进行比较,而不是按值进行比较。
在 C# 中,您不能为静态 class 编写扩展来调用 EqualityComparer<T>.ForCollection
,但您可以使用 F#:
module EqualityComparer =
let ForCollection<'a> = ...
let def = EqaulityComparer.Default
let mine = EqualityComparer.ForCollection
如您所见,我们用 module
扩展了 static class
。这是 2 个具有相同名称的不同类型,我们可以使用两者的方法和属性。
Map
class和Map
模块也是如此。您已经为可以实例化的类型创建了别名,但还没有为辅助模块创建别名。您需要做的是为 module
type School = Map<int, string list>
module School = Map
School.empty