F# GreaterThanZero 传递 int 或 decimal
F# GreaterThanZero passing int or decimal
我想创建一个函数来检查传递的值是否大于零。
传递的值可以是整数或小数(理想情况下是“数值”)。
我刚开始是这样的:
type number =
| I of int
| D of decimal
type Checker () =
member this.Validate value =
match value with
| I x when x > 0 -> "ok"
| D x when x > 0m -> "ok"
| _ -> "error"
let a = 1f
let b = 1m
//let a_IsValid = Checker().Validate(a) // does not compile, expect number (not int)
//let b_IsValid = Checker().Validate(b) // does not compile, expect number (not decimal)
发现不能立即传递“数字”,所以尝试了不同的方法...
我找到了这篇文章 (http://tomasp.net/blog/fsharp-generic-numeric.aspx/),我想
“静态成员约束”对我来说是完美的解决方案。
一个基本示例按预期工作:
let inline divideByTwo value =
LanguagePrimitives.DivideByInt value 2
divideByTwo 1f |> ignore
divideByTwo 1m |> ignore
但一个不同的场景让我感到非常惊讶:
type Calculator () =
let divideByTwo value =
LanguagePrimitives.DivideByInt value 2
member this.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
member this.ValidateGeneric value =
match LanguagePrimitives.GenericGreaterThan value 0m with
| true -> "ok"
| _ -> "error"
//let half = Calculator().DivideByTwo(1) // DivideByInt does not support int !!
// cannot use both the following, the first one will "force" the type, and the other will not work
let a_half = Calculator().DivideByTwo(1f) // ok if used before the "decimal" version
let b_half = Calculator().DivideByTwo(1m) // ok only if comment the previous one
当我想为传递值使用多种类型时,它似乎不起作用。
不仅如此,我需要的功能(GenericGreaterThan
)似乎还有另一个“限制”,下面解释。
文章中的示例使用 DivideByInt
,正如其名称所示,它将传递的值除以 一个 int,这是一种定义明确的类型。
LanguagePrimitives.GenericGreaterThan
需要 2 个参数,一个传递值和一个用于比较的固定值。函数的签名仅作为两者的一种通用类型,因此如果您传递一个类型 'T,它期望第二个类型也是 'T。
我只想与 zero 比较而不传递它,但是使用“0”强制我的值
为 int 并使用“0m”强制该值为小数。
有一种简单的方法可以让函数检查“数字”值是否大于“零”?
我应该使用 obj 并将其装箱....还是使用 cast ... 或停止尝试并为我需要的每种类型使用不同的函数?
[更新]
我尝试按照建议使用 LanguagePrimitives.GenericZero
,但仍然无法为我的特定场景提供有效的解决方案。
我在这里创建了一个新问题: .
这里有很多东西。
您的第一个示例不起作用,因为您需要将您的数字包装在类型编号中(我假设您意识到了这一点?但不希望它那样工作?)
type Checker () =
member this.Validate value =
match value with
| I x when x > 0 -> "ok"
| D x when x > 0m -> "ok"
| _ -> "error"
let a = I 1
let b = D 1m
let a_IsValid = Checker().Validate(a)
let b_IsValid = Checker().Validate(b)
你的第二个例子是in不支持除以int?
是的 1/2 的值是多少?它不是一个整数,所以这是设计正确的。
第三个问题似乎是这段代码无法编译并且 运行?
type Calculator () =
member inline _.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
let b_half = Calculator().DivideByTwo(1m) // ok for me
let a_half = Calculator().DivideByTwo(1f) // ok for me
但这对我有用。
第四个问题似乎是需要使用静态约束来测试是否大于 0?
但是 0(在数学中)在不同的数字系统中是不同的东西,它也是通用的,所以你需要 LanguagePrimitives.GenericZero。把所有这些放在一起我们得到
type Calculator () =
member inline _.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
member inline _.ValidateGeneric value =
match LanguagePrimitives.GenericGreaterThan
value
LanguagePrimitives.GenericZero with
| true -> "ok"
| _ -> "error"
let b_half = Calculator().DivideByTwo(1m)
let a_half = Calculator().DivideByTwo(1f)
let y = Calculator().ValidateGeneric(1m)
let z = Calculator().ValidateGeneric(1f)
关于除以1/2的问题,你可能需要想想你想让它做什么?输入类型真的是由你想要的输出类型定义的吗?十进制?漂浮?等等
一般地与零进行比较实际上非常简单。以下函数适用于任何数字类型:
let inline isPositive x =
x > LanguagePrimitives.GenericZero
isPositive 1.0 |> printfn "%A" // true
isPositive 1m |> printfn "%A" // true
一般除以二也很容易。您只需要定义自己的通用两个,因为它不是 built-in 原语:
let inline divideByTwo x =
let two =
LanguagePrimitives.GenericOne
+ LanguagePrimitives.GenericOne
x / two
divideByTwo 5.0 |> printfn "%A" // 2.5
divideByTwo 4m |> printfn "%A" // 2
我想创建一个函数来检查传递的值是否大于零。
传递的值可以是整数或小数(理想情况下是“数值”)。
我刚开始是这样的:
type number =
| I of int
| D of decimal
type Checker () =
member this.Validate value =
match value with
| I x when x > 0 -> "ok"
| D x when x > 0m -> "ok"
| _ -> "error"
let a = 1f
let b = 1m
//let a_IsValid = Checker().Validate(a) // does not compile, expect number (not int)
//let b_IsValid = Checker().Validate(b) // does not compile, expect number (not decimal)
发现不能立即传递“数字”,所以尝试了不同的方法... 我找到了这篇文章 (http://tomasp.net/blog/fsharp-generic-numeric.aspx/),我想 “静态成员约束”对我来说是完美的解决方案。 一个基本示例按预期工作:
let inline divideByTwo value =
LanguagePrimitives.DivideByInt value 2
divideByTwo 1f |> ignore
divideByTwo 1m |> ignore
但一个不同的场景让我感到非常惊讶:
type Calculator () =
let divideByTwo value =
LanguagePrimitives.DivideByInt value 2
member this.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
member this.ValidateGeneric value =
match LanguagePrimitives.GenericGreaterThan value 0m with
| true -> "ok"
| _ -> "error"
//let half = Calculator().DivideByTwo(1) // DivideByInt does not support int !!
// cannot use both the following, the first one will "force" the type, and the other will not work
let a_half = Calculator().DivideByTwo(1f) // ok if used before the "decimal" version
let b_half = Calculator().DivideByTwo(1m) // ok only if comment the previous one
当我想为传递值使用多种类型时,它似乎不起作用。
不仅如此,我需要的功能(GenericGreaterThan
)似乎还有另一个“限制”,下面解释。
文章中的示例使用 DivideByInt
,正如其名称所示,它将传递的值除以 一个 int,这是一种定义明确的类型。
LanguagePrimitives.GenericGreaterThan
需要 2 个参数,一个传递值和一个用于比较的固定值。函数的签名仅作为两者的一种通用类型,因此如果您传递一个类型 'T,它期望第二个类型也是 'T。
我只想与 zero 比较而不传递它,但是使用“0”强制我的值
为 int 并使用“0m”强制该值为小数。
有一种简单的方法可以让函数检查“数字”值是否大于“零”? 我应该使用 obj 并将其装箱....还是使用 cast ... 或停止尝试并为我需要的每种类型使用不同的函数?
[更新]
我尝试按照建议使用 LanguagePrimitives.GenericZero
,但仍然无法为我的特定场景提供有效的解决方案。
我在这里创建了一个新问题:
这里有很多东西。
您的第一个示例不起作用,因为您需要将您的数字包装在类型编号中(我假设您意识到了这一点?但不希望它那样工作?)
type Checker () =
member this.Validate value =
match value with
| I x when x > 0 -> "ok"
| D x when x > 0m -> "ok"
| _ -> "error"
let a = I 1
let b = D 1m
let a_IsValid = Checker().Validate(a)
let b_IsValid = Checker().Validate(b)
你的第二个例子是in不支持除以int? 是的 1/2 的值是多少?它不是一个整数,所以这是设计正确的。
第三个问题似乎是这段代码无法编译并且 运行?
type Calculator () =
member inline _.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
let b_half = Calculator().DivideByTwo(1m) // ok for me
let a_half = Calculator().DivideByTwo(1f) // ok for me
但这对我有用。
第四个问题似乎是需要使用静态约束来测试是否大于 0?
但是 0(在数学中)在不同的数字系统中是不同的东西,它也是通用的,所以你需要 LanguagePrimitives.GenericZero。把所有这些放在一起我们得到
type Calculator () =
member inline _.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
member inline _.ValidateGeneric value =
match LanguagePrimitives.GenericGreaterThan
value
LanguagePrimitives.GenericZero with
| true -> "ok"
| _ -> "error"
let b_half = Calculator().DivideByTwo(1m)
let a_half = Calculator().DivideByTwo(1f)
let y = Calculator().ValidateGeneric(1m)
let z = Calculator().ValidateGeneric(1f)
关于除以1/2的问题,你可能需要想想你想让它做什么?输入类型真的是由你想要的输出类型定义的吗?十进制?漂浮?等等
一般地与零进行比较实际上非常简单。以下函数适用于任何数字类型:
let inline isPositive x =
x > LanguagePrimitives.GenericZero
isPositive 1.0 |> printfn "%A" // true
isPositive 1m |> printfn "%A" // true
一般除以二也很容易。您只需要定义自己的通用两个,因为它不是 built-in 原语:
let inline divideByTwo x =
let two =
LanguagePrimitives.GenericOne
+ LanguagePrimitives.GenericOne
x / two
divideByTwo 5.0 |> printfn "%A" // 2.5
divideByTwo 4m |> printfn "%A" // 2