F# 匹配记录和区分联合

F# matching records and discriminated unions

我想使用 calculateWage 函数,它给出了一个错误,应该是 Employee 类型,但这里是 Person 类型。

type Person =
    { first_name: string
      last_name: string
      age: int
      salary_hour: int }

type Employee =
    | Administrator of Person
    | OfficeWorker of Person
    | WarehouseWorker of Person

let calculateWage (employee:Employee) (hours:int) = 
    match employee with
    | {salary_hour= sh} ->  (sh * hours)*TAX/100
   


您需要匹配员工以获取信息:


let calculateWage (employee:Employee) (hours:int) = 
    match employee with
    | Administrator person -> 
      (person.salary_hour * hours)*TAX/100})
    | OfficeWorker person -> ...
    | WarehouseWorker person -> ...

或者,更改计算工资以接受 Person 作为参数。

如果所有人都使用相同的计算,但需要用 DU 包装,这将特别有用。

我已经编辑了两次,因为一个令人尴尬的错字。汤姆从一开始就拥有权利

您需要像这样在被区分的联合上进行匹配:

let calculateWage (employee:Employee) (hours:int) = 
    match employee with
    | Administrator {salary_hour= sh}
    | OfficeWorker {salary_hour= sh}
    | WarehouseWorker {salary_hour= sh} ->  (sh * hours)*TAX/100

在这种情况下,它可能看起来很愚蠢,但请记住,每个受歧视的联合案例都可以有不同的数据。

通常当我得到这样的数据时,我会分两步进行。我有一个提取公共数据的函数。以及一个处理数据本身的函数:

let extractPerson employee =
    match employee with
    | Administrator p
    | OfficeWorker p
    | WarehouseWorker p -> p

let calculateWage person (hours:int) =
    (person.salary_hour * hours)*TAX/100

所以你最终得到了一些你可以轻松编写的函数:

let calculate employee =
   employee
   |> extractPerson 
   |> calculateWage 

我会选择 ,但是如果您坚持要在模式匹配中解构 Employee,您可以轻松地将其转换为由“banana clips”包围的活动识别器":

let (|Employee|) = function
| Administrator p
| OfficeWorker p
| WarehouseWorker p -> p

let calculateWage (employee:Employee) (hours:int) = 
    match employee with
    | Employee{salary_hour= sh} ->  (sh * hours)*TAX/100