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



我有各种各样的值,我想保持在特定的边界之间:例如,列的宽度从10到50(包括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

最新更新