F#中类型的最大/最小值

时间:2014-10-25 10:42:34

标签: .net f# max minimum unchecked

Unchecked.defaultof<'T>为任何类型生成默认值。是否存在这样的通用函数来为具有最大/最小值的类型有意义的任何类型生成最大/最小值?

编辑

回答约翰帕尔默关于我认为哪些内容有用的问题:我想创建一个&#34;可变的&#34;以下功能的版本:

let InternalArrDiffMax (s : 'T []) (diff : 'T -> 'T -> 'C) =
    s
    |> Array.mapi (fun i e -> 
        [| for j in i + 1 .. s.Length - 1 -> diff e s.[j] |]
        |> Array.maxBy (fun n -> n))
    |> Array.maxBy (fun e -> e)

由于我无法在不为其赋值的情况下声明可变变量,因此我认为还有其他方法可以做到:

let InternalArrDiffMax (s : 'T []) (diffFun : 'T -> 'T -> 'C) =
    let mutable max : 'C = // Generic max of 'C if it makes sense

    for i in 0 .. s.Length - 1 do
        for j in i + 1 .. s.Length - 1 do
            let diff = diffFun s.[i] s.[j]
            if (i = 0 && j = 1) || max < diff then
                max <- diff

    max

这就是为什么我认为我需要一个通用的最大值

3 个答案:

答案 0 :(得分:7)

@ kaefer的回答为您提供了获取最大/最小值的好方法,但对于您的特定用例,我建议您改为使用可变变量'C option,并将其初始化为None 。这种方式不需要魔法数字。

let InternalArrDiffMax (s : 'T []) (diffFun : 'T -> 'T -> 'C) =
    let mutable max : 'C option = None

    for i in 0 .. s.Length - 1 do
        for j in i + 1 .. s.Length - 1 do
            let diff = diffFun s.[i] s.[j]
            match max with
            | None -> 
                max <- Some diff
            | Some v when v < diff -> 
                max <- Some diff
            | _ -> ()

    max

答案 1 :(得分:3)

如果你必须继续这条路线,总会有反思。但是,我建议不要使用MaxValue作为带外或特殊值。

let inline tryGetMaxValue< ^a> () =
    match typeof< ^a>.GetField("MaxValue") with
    | null -> None
    | fieldInfo -> fieldInfo.GetValue() |> unbox< ^a> |> Some

let maxvi = tryGetMaxValue<int>()            // val maxvi : int option = Some 2147483647
let maxvf : float option = tryGetMaxValue()  // val maxvf : float option = Some 1.797693135e+308
let maxvs : string option = tryGetMaxValue() // val maxvs : string option = None

答案 2 :(得分:2)

没有反思的方法

let maxOfT (x:'t) : 't = 
  match typedefof<'t> with
  | u when u=typedefof<Int16> -> Int16.MaxValue :> obj
  | u when u=typedefof<Int32> -> Int32.MaxValue :> obj
  // ... repeat for each type
  | _ -> failwith "unrecognised"
  :?> 't
let minOfT (x:'t) : 't = 
  match typedefof<'t> with
  | u when u=typedefof<Int16> -> Int16.MinValue :> obj
  | u when u=typedefof<Int32> -> Int32.MinValue :> obj
  // ... repeat for each type
  | _ -> failwith "unrecognised"
  :?> 't