Generics 使用数值泛型获取本机数值类型的最小/最大值,Int32.MaxValue不';似乎不存在
我需要一个数值通用函数,可以访问数值类型的Generics 使用数值泛型获取本机数值类型的最小/最大值,Int32.MaxValue不';似乎不存在,generics,f#,Generics,F#,我需要一个数值通用函数,可以访问数值类型的MinValue和MaxValue。因为所有的BCL类型都有这些成员,我想我可以这样写: let inline zeroOrMax(x: ^a) = match x with | a when a = LanguagePrimitives.GenericZero -> x | a when a = LanguagePrimitives.GenericOne -> let maxVal = (^a: (
MinValue
和MaxValue
。因为所有的BCL类型都有这些成员,我想我可以这样写:
let inline zeroOrMax(x: ^a) =
match x with
| a when a = LanguagePrimitives.GenericZero -> x
| a when a = LanguagePrimitives.GenericOne ->
let maxVal = (^a: (static member MaxValue : ^a) ())
maxVal
| a when -a = LanguagePrimitives.GenericOne ->
let maxVal = (^a: (static member MaxValue : ^a) ())
-maxVal
| _ -> ...
此函数将为您提供基础类型的零或(负/正)最大值
当我创建自己的类型实现MaxValue
,但Int32
,Int64
等具有静态成员MaxValue
和MinValue
时,我会不断得到静态编译错误,该参数没有表示静态成员:
let test (x: int64) =
// error FS0001: The type 'int64' does not support the operator 'get_MaxValue'
zeroOrMax x
我想这是因为F#特别对待这些类型。或者我只是需要一种不同的语法。在保持数值泛型和访问基础类型的最小/最大值的同时,是否有办法解决此问题?静态解析的类型成员约束不考虑字段 如注释中所述,您可以使用create这样的泛型函数,它通过为每个已知类型指定重载来完成您想要的任务 以下是“独立”版本的:
开放系统
键入MaxValue=MaxValue并加上
静态成员($)((单位:,最大值)=()
静态成员($)(u0:bool,0:MaxValue)=true
静态成员($)(u:char,u:MaxValue)=char.MaxValue
静态成员($)(u:byte,u:MaxValue)=byte.MaxValue
静态成员($)(yte:sbyte,yte:MaxValue)=sbyte.MaxValue
静态成员($)(quot:float,quot:MaxValue)=Double.MaxValue
静态成员($)(u:int16,u:MaxValue)=int16.MaxValue
静态成员($)(\u0:int,\u0:MaxValue)=Int32.MaxValue
静态成员($)(u:int64,u:MaxValue)=int64.MaxValue
静态成员($)(u:float32,u:MaxValue)=Single.MaxValue
静态成员($)(uint16,uint16:MaxValue)=uint16.MaxValue
静态成员($)(u3;:uint32,3;:MaxValue)=uint32.MaxValue
静态成员($)(u0:uint64,0:MaxValue)=uint64.MaxValue
静态成员($)(quo:decimal,quo:MaxValue)=decimal.MaxValue
静态成员($)(u:DateTime,u:MaxValue)=DateTime.MaxValue
静态成员($)(u:DateTimeOffset,u:MaxValue)=DateTimeOffset.MaxValue
静态成员($)(quo:TimeSpan,quo:MaxValue)=TimeSpan.MaxValue
让内联maxValue():'r=Unchecked.defaultofint64.maxValue
是一个成员常量,而不是一个属性。@fyodor ouch,dejavu,感觉就像我之前看到的那样。我猜没有比这更简单的解决办法了?不,没有办法。我创建了一个这样做的。你可以使用它,也可以复制那里的代码。@Gustavo,有趣的方法。我是按照这些思路思考的(我希望把一些事情放在一起,我想这还不会发生)。另一种欺骗系统的方式导致了F#的奇怪(或不是?)行为。有趣的错误报告,一如既往。我将从该泛型函数中添加一些代码作为答案。
open System
type MaxValue = MaxValue with
static member ($) (_:unit , _:MaxValue) = ()
static member ($) (_:bool , _:MaxValue) = true
static member ($) (_:char , _:MaxValue) = Char.MaxValue
static member ($) (_:byte , _:MaxValue) = Byte.MaxValue
static member ($) (_:sbyte , _:MaxValue) = SByte.MaxValue
static member ($) (_:float , _:MaxValue) = Double.MaxValue
static member ($) (_:int16 , _:MaxValue) = Int16.MaxValue
static member ($) (_:int , _:MaxValue) = Int32.MaxValue
static member ($) (_:int64 , _:MaxValue) = Int64.MaxValue
static member ($) (_:float32 , _:MaxValue) = Single.MaxValue
static member ($) (_:uint16 , _:MaxValue) = UInt16.MaxValue
static member ($) (_:uint32 , _:MaxValue) = UInt32.MaxValue
static member ($) (_:uint64 , _:MaxValue) = UInt64.MaxValue
static member ($) (_:decimal , _:MaxValue) = Decimal.MaxValue
static member ($) (_:DateTime , _:MaxValue) = DateTime.MaxValue
static member ($) (_:DateTimeOffset, _:MaxValue) = DateTimeOffset.MaxValue
static member ($) (_:TimeSpan , _:MaxValue) = TimeSpan.MaxValue
let inline maxValue() :'r = Unchecked.defaultof<'r> $ MaxValue
type MaxValue with
static member inline ($) ((_:'a*'b ), _:MaxValue) = maxValue(), maxValue()
static member inline ($) ((_:'a*'b*'c ), _:MaxValue) = maxValue(), maxValue(), maxValue()
static member inline ($) ((_:'a*'b*'c*'d ), _:MaxValue) = maxValue(), maxValue(), maxValue(), maxValue()
static member inline ($) ((_:'a*'b*'c*'d*'e), _:MaxValue) = maxValue(), maxValue(), maxValue(), maxValue(), maxValue()
// Usage
let x:int = maxValue()
// val x : int = 2147483647
let y:int * float *TimeSpan = maxValue()
// val y : int * float * TimeSpan = (2147483647, 1.797693135e+308, 10675199.02:48:05.4775807)