如何实例化一个'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 个具有相同名称的不同类型,我们可以使用两者的方法和属性。

MapclassMap模块也是如此。您已经为可以实例化的类型创建了别名,但还没有为辅助模块创建别名。您需要做的是为 module

创建类型缩写
type School = Map<int, string list>
module School = Map

School.empty