F#使用通用度量单位创建通用函数

时间:2018-01-05 18:35:41

标签: generics f# units-of-measurement

我觉得我可能正在以F#想要考虑类型和度量单位的方式进行战斗,但我想问这个问题,以防我错过了一些明显的东西。我使用类型和度量单位作为确保所有操作都具有类型对齐的方法。我想要定义一个通用的tryDivide函数,该函数将采用匹配的类型,但我正在试图使它工作的圈子中运行这是非通用的版本:

[<Measure>] type USD (* US Dollars *)

let tryDivide a b =
    match b > 0M with
    | true -> a / b |> decimal |> Some
    | false -> None


type Cost = decimal<USD>

module Cost =
    let create v : Cost =
        v * 1M<USD>

    let tryDivide (a:Cost) (b:Cost) =
        tryDivide (decimal a) (decimal b)

let costA = Cost.create 10M
let costB = Cost.create 20M

let ratio = Cost.tryDivide costA costB

问题是我必须为每种类型定义tryDivide函数(例如:Cost.tryDivide)。是否有某种方法可以使顶级tryDivide函数对于类型和度量单位具有通用性?理想情况下,它将采用任何类型,它实际上只是一个decimal<'u>,它具有度量单位。我尝试了各种功能签名但没有任何作用。如果我执行以下操作,则会将输入限制为int

let tryDivide (a: 'u) (b: 'u) =
    let x = (decimal a)
    let y = (decimal b)
    match y > 0M with
    | true -> x / y |> decimal |> Some
    | false -> None

如果我的思维过程根本错误,我很乐意听到。我为每种类型代码tryDivide,这似乎效率低下。

1 个答案:

答案 0 :(得分:1)

我找到了答案。您需要在单位上设置b > 0M通用。为此,您需要打开Microsoft.FSharp.Core.LanguagePrimitives模块并使用DecimalWithMeasure功能。以下是tryDivide函数的新版本:

let tryDivide a b =
    match b > (DecimalWithMeasure 0M) with
    | true -> a / b |> Some
    | false -> None