【问题标题】:Maximum / minimum value of type in F#F#中类型的最大值/最小值
【发布时间】:2014-10-25 10:42:34
【问题描述】:

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

编辑

回答 John Palmer 关于我认为它在哪里有用的问题:我想创建以下函数的“可变”版本:

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

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

【问题讨论】:

  • 我不这么认为(好吧,从来没有见过这样的东西 - 也许有一个) - IMO 这没有多大意义因为没有 所有类型的最大值。
  • 你到底想做什么?以通用方式获得最大值可能不是特别有用
  • 参见github.com/gmpl/FsControl,按照hackage.haskell.org/package/base-4.7.0.1/docs/…中的定义实现Bounded,然后发送拉取请求。
  • @MauricioScheffer 好建议。我只是 added 给 FsControl 。
  • @Gustavo:你能做一个 FsControl.Core 中 Bounded 的示例用法吗?

标签: .net f# max minimum unchecked


【解决方案1】:

@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

【讨论】:

  • 这是解决我潜在问题的优雅方法,但我不得不将@kaefer 的回复标记为答案。我想投票给你,但我什至没有足够的声誉来这样做......无论如何谢谢:-)
  • @bugfoot:当然,我不介意。他回答了这个问题。你可以随时回来投票;)
【解决方案2】:

如果您必须沿着这条路线前进,总会有反思。但是,我建议不要将 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

【讨论】:

    【解决方案3】:

    没有反思的方法

    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
    

    【讨论】:

    • 这是部分的并且破坏了参数化。不推荐。
    • @MauricioScheffer:.Net 中的 MaxValue / MinValue 是一个静态约定。请告知哪些解决方案不会破坏参数化。
    • 见上面古斯塔沃的评论和链接。
    • @MauricioScheffer:感谢您的提醒。一个有用的补充。我同意“有界”的需要,但我也想要一种检索 minValue 或 maxValue 的功能性方法。我会 ping Gustavo。
    • @MauricioScheffer:实际上,在考虑之后,在大多数情况下,我更喜欢您的建议 + Gustavo 的实现。感谢您错误地将类型安全放在首位,从而将负载放在编译器上。这就是你对参数化的理解,对吧?
    猜你喜欢
    • 1970-01-01
    • 2019-01-02
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多