【问题标题】:Pattern matching record types模式匹配记录类型
【发布时间】:2011-10-29 22:12:01
【问题描述】:

让我们考虑以下Point 记录类型:

type Point = { x:int; y:int }

我想创建一个谓词,告诉我给定点是否在有效区域中。

let insideBounds p =
  let notInside c = c < 0 || c > 100
  match p with
  | {x=i; y=_} when notInside i -> false
  | {x=_; y=j} when notInside j -> false
  | _                           -> true

这行得通,但我想知道是否有另一种方法可以实现与 insideBounds 签名相同的结果

let insideBounds {x=i; y=j}

相反,仍然使用模式匹配?

【问题讨论】:

    标签: .net f# functional-programming pattern-matching


    【解决方案1】:

    当然。

    type Point = { x:int; y:int }
    
    let insideBounds {x=i; y=j} =
      let notInside c = c < 0 || c > 100
      not (notInside i || notInside j)
    

    我建议颠倒您的逻辑以使其更清晰:

    let insideBounds {x=i; y=j} =
      let isInside c = c >= 0 && c <= 100
      isInside i && isInside j
    

    作为一般规则,布尔函数/属性等最好是肯定的。这样,否定就保留了它的否定性,可以这么说。

    【讨论】:

    • 很抱歉我不够清楚。您的解决方案比我上面显示的要好得多(我实际上使用的是 exactly 与您在我自己的代码中显示的相同的解决方案)。我只是想了解如何使用该函数签名完成模式匹配。
    • 重要的是模式匹配出现在很多地方,包括函数参数。 msdn.microsoft.com/en-us/library/dd547125.aspx(见备注)
    【解决方案2】:

    您可以定义一个活动模式,以测试一个值是否在指定为参数的范围内:

    let (|InRange|_|) (min, max) v = 
      if v >= min && v <= max then Some () else None
    

    然后你可以这样定义insideBounds

    let insideBounds = function
      | { x = InRange (0, 100); y = InRange (0, 100) } -> true
      | _ -> false
    

    xy 两个成员都在指定范围内时,第一种情况匹配。活动模式返回option unit,这意味着它不绑定任何值。 (0, 100) 是输入参数,当值(xy)在范围内时,模式匹配。

    (在其他上下文中`匹配 10 与 InRange (0

    【讨论】:

    • 然后可以用函数式风格轻松重写:let insideBounds {x=i; y=j} = let inRange = ((|InRange|_|) (0, 100) &gt;&gt; Option.isSome); inRange i &amp;&amp; inRange j :-)
    • @Tomas 太酷了。模式匹配语句的行为类似于 Maybe 模式。
    猜你喜欢
    • 2013-06-14
    • 1970-01-01
    • 2020-10-21
    • 2016-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-19
    • 2013-06-25
    相关资源
    最近更新 更多