F#-这是验证并保持两个边界之间的值的好方法吗?

问题描述

我具有各种数值,希望将它们保持在一定范围内:例如列的宽度从10到50(含);或行数从1到100(含1和100)之间。这些值来自我的F#代码外部的进程。

当给定值降到下限以下时,我希望给定该值的最小界限值。 当给定值超出上限时,我希望给定该值的最大界限值。 否则,我会接受给定的值。

例如:

界限= 10到50 –给定值= 3 –结果值= 10

界限= 10到50 –给定值= 200 –结果值= 50

界限= 10到50 –给定值= 32 –结果值= 32

我想出了一些代码,但是我不确定这是不是做得太过分,还是我这样做很愚蠢。 看起来很容易推断其工作原理,但我不确定,无缘无故。

type ValueAndBounds = { Value : int; Lower : int; Upper: int }

let (|TooSmall|TooLarge|CorrectSize|) input =
    if input.Value < input.Lower then TooSmall
    elif input.Value > input.Upper then TooLarge
    else CorrectSize

let keepWithinBounds input =
    match input with
    | TooSmall -> input.Lower
    | TooLarge -> input.Upper
    | CorrectSize -> input.Value

type ColumnWidth = ColumnWidth of int

let width = ColumnWidth (keepWithinBounds { Value = 32; Lower = 10; Upper = 50 })

有什么办法可以改善这一点?

对于这种简单的事情,我走得太远了吗(这超出了必要)吗?

是否有更好的方法可以做到这一点?

解决方法

我个人只是定义一个简单的函数,并使用一些局部应用程序,

let keepWithBounds min max value = 
    if (value < min) then
        min
    elif (value > max) then
        max
    else 
        value

然后您的代码可以执行类似的操作

let handleWidth = keepWithBounds 10 50
let width1 = handleWidth 32
let width2 = handleWidth 60
,

这是我自己的答案,它同时使用活动模式和部分应用程序,并允许通用使用而无需其他类型。

let (|TooSmall|TooLarge|CorrectSize|) (lower,upper,input) =
   if input < lower then TooSmall
   elif input > upper then TooLarge
   else CorrectSize
 
let keepWithinBounds lowerBound upperBound input =
   match (lowerBound,upperBound,input) with
   | TooSmall -> lowerBound
   | TooLarge -> upperBound
   | CorrectSize -> input
 
type ColumnWidth = ColumnWidth of int
type RowHeight = RowHeight of int
type Temperature = Temperature of float
 
let createColumnWidth = keepWithinBounds 10 40
let createRowHeight = keepWithinBounds 60 100
let createTemperature = keepWithinBounds 0.0 20.0
 
let width = ColumnWidth (createColumnWidth 50)
let height = RowHeight (createRowHeight 50)
let temp = Temperature (createTemperature 33.1)

//val width : ColumnWidth = ColumnWidth 40
//val height : RowHeight = RowHeight 60
//val temp : Temperature = Temperature 20.0