Максимальное/минимальное значение типа в F#

Unchecked.defaultof<'T> генерирует значение по умолчанию для любого типа. Существует ли такая общая функция для генерации максимального/минимального значения для любого типа, где имеет смысл тип, имеющий максимальное/минимальное значение?

ИЗМЕНИТЬ

Чтобы ответить на вопрос Джона Палмера о том, где, по моему мнению, это было бы полезно: я хочу создать «изменяемую» версию приведенной ниже функции:

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

Вот почему я думаю, что мне нужен общий макс.


person bugfoot    schedule 25.10.2014    source источник
comment
Я так не думаю (никогда не видел ничего подобного - может быть, он и есть) - IMO это не имело бы особого смысла, потому что нет максимума для все типы.   -  person Random Dev    schedule 25.10.2014
comment
Что вы на самом деле пытаетесь сделать? получение максимума общим способом, вероятно, не особенно полезно   -  person John Palmer    schedule 25.10.2014
comment
См. github.com/gmpl/FsControl , реализуйте Bounded, как определено в hackage.haskell.org/package/base-4.7.0.1/docs/ , затем отправьте запрос на извлечение.   -  person Mauricio Scheffer    schedule 26.10.2014
comment
@MauricioScheffer Хорошее предложение. Я просто добавил его в FsControl .   -  person Gus    schedule 27.10.2014
comment
@Gustavo: не могли бы вы привести пример использования Bounded в FsControl.Core?   -  person sgtz    schedule 17.11.2014
comment
Конечно, @sgtz вот это github.com/gmpl/FsControl/commit/   -  person Gus    schedule 17.11.2014
comment
@ Густаво: вау. Действительно элегантный. ты. Тип MaxValue = MaxValue где-то задокументирован? Я понимаю, что это своего рода объединение, но не смог найти обозначение здесь или здесь.   -  person sgtz    schedule 18.11.2014
comment
@sgtz Точно, это тип, который фактически представляет метод, поэтому я называю его методом типа, в основном это DU типа или одиночного случая, который содержит перегруженные методы. Этот метод частично задокументирован в файле проекта readme.md, но вы можете найти дополнительную информацию в моих старых сообщениях по адресу nut- взломщик.azurewebsites.net. Примеры файлов также полезны. Я не думаю, что вы найдете что-нибудь об этой технике на сайтах Microsoft.   -  person Gus    schedule 18.11.2014


Ответы (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
person kaefer    schedule 25.10.2014

Ответ @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
person scrwtp    schedule 25.10.2014
comment
Это элегантное решение моей основной проблемы, но мне пришлось пометить ответ @kaefer как ответ. Я бы хотел проголосовать за вас, но у меня даже недостаточно репутации для этого... В любом случае спасибо :-) - person bugfoot; 25.10.2014
comment
@bugfoot: Конечно, я не против. Он ответил на вопрос. Вы всегда можете вернуться, чтобы проголосовать ;) - person scrwtp; 25.10.2014

Подход без размышлений

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
person sgtz    schedule 25.10.2014
comment
Это частично и нарушает параметричность. Не рекомендую. - person Mauricio Scheffer; 26.10.2014
comment
@MauricioScheffer: MaxValue / MinValue в .Net является статическим соглашением. Посоветуйте, пожалуйста, какие решения не нарушают параметричность. - person sgtz; 26.10.2014
comment
См. комментарий Густаво и ссылку выше. - person Mauricio Scheffer; 28.10.2014
comment
@MauricioScheffer: спасибо за предупреждение. Полезное дополнение. Я согласен с необходимостью ограничения, но мне также нужен функциональный способ получения minValue или maxValue. Я позвоню Густаво. - person sgtz; 28.10.2014
comment
@MauricioScheffer: на самом деле, подумав об этом, в большинстве случаев я предпочитаю ваше предложение + реализацию Густаво. Спасибо, что допустили ошибку, возложив нагрузку на компилятор, поставив безопасность типов на первое место. Это то, что вы имели в виду с параметричностью, верно? - person sgtz; 28.10.2014
comment
см. dl.dropboxusercontent.com/u/7810909/media/doc/parametricity .pdf для хорошего введения в параметризацию. - person Mauricio Scheffer; 28.10.2014
comment
@MauricioScheffer ты. - person sgtz; 28.10.2014