简化模式匹配

Simplifying pattern match

我有这些类型

type IntervalWithBreak = { Start: DateTime; End: DateTime }
type IntervalWithoutBreak = { Start: DateTime; End: DateTime; Break: TimeSpan }

type WorkTime =
  | Workshop of IntervalWithBreak
  | Mounting of IntervalWithBreak
  | Ill of IntervalWithoutBreak
 
type WorktimeDefinition = {Weekday: DayOfWeek}

现在我想创建一个函数来查找与条件匹配的元素。 matches 函数中 workTime 的代码完成在我使用此模式匹配之前不提供 StartEnd 字段。

let matches (worktime:WorkTime) (worktimeDefinition:WorktimeDefinition) =
  match worktime with
  | Workshop w -> w.Start.DayOfWeek = worktimeDefinition.Weekday
  | Mounting m -> m.Start.DayOfWeek = worktimeDefinition.Weekday
  | Ill i -> i.Start.DayOfWeek = worktimeDefinition.Weekday

List.find (matches worktime) definitions

我可以有一个更通用的匹配,这样我就不必检查所有联合案例,而是匹配 IntervalWithoutBreakIntervalWithBreak 吗?

我的类型定义基于

由于Workshop case 和Mounting case 的参数属于同一类型,首先你可以做的是将它们连接成一个或模式:

let matches (worktime:WorkTime) (worktimeDefinition:WorktimeDefinition) =
  match worktime with
  | Workshop m 
  | Mounting m -> m.Start.DayOfWeek = worktimeDefinition.Weekday
  | Ill i -> i.Start.DayOfWeek = worktimeDefinition.Weekday

这不适用于包含不同类型参数的 Ill 情况。但是因为都是记录,所以你也可以在模式匹配中解构记录:

let matches (worktime:WorkTime) (worktimeDefinition:WorktimeDefinition) =
  match worktime with
  | Workshop { Start = start } 
  | Mounting { Start = start }
  | Ill { Start = start } -> start.DayOfWeek = worktimeDefinition.Weekday

因为你现在只有一个案例,你实际上可以使用 let 来写这个,但我可能不会这样做。我认为 match 更具可读性。但仅作记录:

let matches (worktime:WorkTime) (worktimeDefinition:WorktimeDefinition) =
  let (Workshop { Start = s } | Mounting { Start = s } | Ill { Start = s }) = worktime
  s.DayOfWeek = worktimeDefinition.Weekday