【问题标题】:Discriminated Union with Integer Values in F#F# 中具有整数值的可区分联合
【发布时间】:2015-04-16 18:23:06
【问题描述】:

我正在尝试编写具有以下签名的 F# 类型:

type Foo = (Distance * Event * Course)

这样你就可以像这样创建一个 Foo:

let bar = (25, Freestyle, LCM)

现在后两部分(事件和课程)很简单——我确信距离也是,我只是还不知道——我只是使用了一个有区别的联合。

假设距离的唯一有效值是 [25;50;100],那么构造距离类型的最佳方法是什么?

【问题讨论】:

  • type Distance = TwentyFive | Fifty | Hundred

标签: f# f#-3.0


【解决方案1】:

我假设目标是轻松访问一个实整数值,但仅限于一定数量的情况。

@Petr 的建议可以正常工作,您只需将枚举值转换为 int。

另一种选择是在 DU 类型的方法中计算值:

type Distance = 
    TwentyFive | Fifty | Hundred
    member this.ToInt() =
        match this with
        | TwentyFive -> 25
        | Fifty -> 50
        | Hundred -> 100

或者如果您想要更强大的语法支持,单案例活动模式可能会更好:

type Event = Freestyle | Backstroke
type Distance = TwentyFive | Fifty | Hundred
let (|IntDistance|) d =
    match d with
    | TwentyFive -> 25
    | Fifty -> 50
    | Hundred -> 100

let race = (Fifty, Freestyle)

let (IntDistance(dist), evt) = race
printfn "Race info: %d %A" dist evt

match race with
| IntDistance(dist), Freestyle -> ...
| IntDistance(dist), Backstroke -> ...

【讨论】:

  • 可能值得考虑使用度量单位的浮点数,而不是数字距离的整数。 我删除了我的答案并用这个评论替换了它,因为它已经晚了几秒钟,并且与这个答案的第一个代码块几乎没有什么不同——除了它使用了带有来自 Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols 的米注释的浮点数。
  • 不保证单位是米,可能是码。课程成员确定计量单位。
  • 我并不希望轻松访问整数值,尽管这会有所帮助。为了与该领域无处不在的语言保持同步,事件将是“25 Free LCM”,其中“LCM”表示“Long Course Meters”,所以我认为类型构造函数需要接受整数值而不是“TwentyFive” “。这有帮助吗?
  • 度量单位可以是通用的,所以它们在这里仍然可能有用
  • 如果您想在编译时键入 system 以强制执行一组有效距离,您需要按照建议使用联合。否则,您需要定义一个将数字作为构造函数参数的类,并在运行时对其进行验证。
【解决方案2】:

您可以使用 .NET 枚举:

type Distance = TwentyFive=25 | Fifty=50 | Hundred=100

对于模式匹配,您必须使用限定名称:Distance.Fifty

【讨论】:

    猜你喜欢
    • 2017-12-27
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 2012-12-14
    • 1970-01-01
    相关资源
    最近更新 更多