如何用 "with" 解构联合?

How to deconstruct union with "with"?

我在使用 "with" 时遇到一些问题:

type NaturalPerson = {
    FirstName: string
    LastName: string
}

type CorporateEntity = {
    Name1: string
    Name2: string option
}

type Person = 
    | Natural of NaturalPerson
    | Company of CorporateEntity

let company = Company { Name1 = "Foo Bar AG"; Name2 = Some "Baz" }

现在我想将 Name2 更改为 None,但我不知道该怎么做。 类似于:

let company2 = Company { company with Name2 = None }

在我的 "real world example" 当然这是嵌套的,否则我可以使用正确的类型。

也许这是不可能的,因为我必须为边缘情况进行模式匹配,而这种情况不存在(但编译器不够聪明,无法知道)。

这是您的操作方法(我假设如果变量 companyNaturalPerson 那么您希望它保持不变):

match company with
| Person _ -> company
| Company corpEntity -> Company { corpEntity with Name2 = None }

如果你把它分解得再多一点,就更容易看出问题所在。事实上,让这一切变得困难的可能是命名。

let company = Company { Name1 = "Foo Bar AG"; Name2 = Some "Baz" } // Person
let company2 = Company { company with Name2 = None } // Person, but broken because expecting company to be type of CorporateEntity

所以您正在尝试创建一个 CorporateEntityPerson 类型,这两个类型是不同的。

之所以有效,是因为使用了正确的类型。

let c1 : CorporateEntity = { Name1 = "Foo Bar AG"; Name2 = Some "Baz" }
let p1 : Person = Company c1
let c2 : CorporateEntity = { c1 with Name2 = None }
let p2 : Person = Company c2

我添加了类型并更改了名称以使类型更明显。 你可以 match 这个...

match company with // <- rename company to person so it is clearer
| Natural _ -> company
| Company c -> Company { c with Name2 = None }

如果你想在一个函数中进行匹配,你可以这样做:

let noCompanyName2 (c:CorporateEntity) = // c:CorporateEntity -> Person
    let { Name1 = n1; Name2 = _ } = c
    let company3 = Company { Name1 = n1; Name2 = None }
    company3

或者更简洁:

let noCompanyName2 ({ Name1 = n1; Name2 = _ }) = Company { Name1 = n1; Name2 = None }

希望这对您有所帮助。