F#中记录的模式匹配

时间:2013-10-11 09:14:05

标签: f# pattern-matching idioms

如何在记录上进行模式匹配是否有更惯用的方法?我的代码似乎不对。

type Period = AM | PM

type TimeOfDay = {hours : int; minutes : int; p : Period}

let before (tod1 : TimeOfDay, tod2 : TimeOfDay) =
   match tod1, tod2 with
   | {hours = h1; minutes = m1; p = AM}, {hours = h2; minutes = m2; p = AM} -> (h1, m1) < (h2, m2)
   | {hours = h1; minutes = m1; p = PM}, {hours = h2; minutes = m2; p = PM} -> (h1, m1) < (h2, m2)
   | {hours = _; minutes = _; p = AM}, {hours = _; minutes = _; p = PM} -> true
   | {hours = _; minutes = _; p = PM}, {hours = _; minutes = _; p = AM} -> false

2 个答案:

答案 0 :(得分:5)

您可以略微改进,因为您不需要显示不需要的模式来生成以下内容

let before (tod1 : TimeOfDay, tod2 : TimeOfDay) =
   match tod1, tod2 with
   | {hours = h1; minutes = m1; p = AM}, {hours = h2; minutes = m2; p = AM} -> (h1, m1) < (h2, m2)
   | {hours = h1; minutes = m1; p = PM}, {hours = h2; minutes = m2; p = PM} -> (h1, m1) < (h2, m2)
   | { p = AM}, {p = PM} -> true
   | { p = PM}, {p = AM} -> false

接下来,您可以定义一个活动模式,将类型解构为元组,如下所示

let (|TIME|) (t:TimeOfDay) = t.hours,t.minutes,t.p

let before (tod1 : TimeOfDay, tod2 : TimeOfDay) =
   match tod1, tod2 with
   | TIME(h1,m1,AM), TIME(h2,m2,PM) -> (h1, m1) < (h2, m2)
   | TIME(h1,m1,PM), TIME(h2,m2,PM) -> (h1, m1) < (h2, m2)
   | { p = AM}, {p = PM} -> true
   | { p = PM}, {p = AM} -> false

答案 1 :(得分:1)

您可以删除比赛中不需要的属性,使用“卫队”(当子句时)检查两个p属性是否相等,并创建一个局部函数以简化元组比较。

let before (tod1: TimeOfDay, tod2: TimeOfDay) =
   let getTime tod = (tod.hours, tod.minutes)
   match tod1, tod2 with
   | { p = x }, { p = y } when x = y -> getTime tod1 < getTime tod2
   | { p = AM }, _ -> true
   | _ -> false

或者只是删除最后一个图案

let before (tod1: TimeOfDay, tod2: TimeOfDay) =
   let getTime tod = (tod.hours, tod.minutes)
   match tod1, tod2 with
   | { p = x }, { p = y } when x = y -> getTime tod1 < getTime tod2
   | { p = x }, _ -> x = AM