【问题标题】:What is the best way to reuse shared fields with F# types?使用 F# 类型重用共享字段的最佳方法是什么?
【发布时间】:2021-03-06 06:40:41
【问题描述】:

我正在编写一个 F# 程序来管理项目列表。所有物品都有名称和价格。食品有保质期,非食品有保质期。我第一次尝试为这个领域建模是这样的:

type Info = {Name : string; Price : decimal;} 

type Item = 
    | Food of Info * DateTime
    | NonFood of Info * TimeSpan

let increasePrice item diff =
    let modifyPrice info =
        {info with Price = info.Price + diff}
    match item with
    | Food (info,expirationDate) -> Food ( modifyPrice info,expirationDate)
    | NonFood (info,warranty) -> NonFood ( modifyPrice info,warranty)

但我不确定这是否是正确的做法。正如您所看到的,这是使用一个(抽象)基类和两个派生子类的 OO 概念建模的。我对 increasePrice 函数必须区分 Items 的两种类型这一事实特别不满意,尽管它只修改了 Item 的一般属性。

是否有更好的方法来使用另一种方法来设计这样的项目列表?

【问题讨论】:

    标签: f#


    【解决方案1】:

    这种方法一般没问题。与 OO 相比,函数式编程通常需要更少的仪式和教条式思维。诸如“function has to identify ... even if ...”之类的问题通常不被视为值得关注,除非有一些实际的实际原因。


    不过,如果(出于某些实际原因)您希望您的食物和非食物项目看起来相似,除非在它们的区别实际上很重要的情况下,实现此目的的一种方法是以另一种方式嵌套您的数据结构周围:

    type Item = { Name: string; Price: decimal; kind: ItemKind }
    type ItemKind = Food of DateTime | NonFood of TimeSpan
    
    let increasePrice item diff = { item with Price = item.Price + diff }
    

    尚不清楚哪种方法“更好”。它们都有优点和缺点,选择取决于你将如何使用这些类型(和函数)。

    【讨论】:

      【解决方案2】:

      另一种方法是故意复制字段,就像这样。这种方法并不少见。

      type Food = { Name: string; Price: decimal; ExpirationDate: DateTime }
      type NonFood = { Name: string; Price: decimal; Warranty: TimeSpan }
      type Item =
          | Food of Food
          | NonFood of NonFood
      

      一般来说,像这样复制字段并没有什么问题,即使每种项目都有一些共同的字段。如果由于许多 DU 案例和/或许多相等字段而导致代码重复或类型重复,那么是时候考虑另一种方法了。否则,这种方法实际上可以大大简化代码 - 更容易推理,更容易阅读。

      实际上,字段 Name 和 Price 是公共结构中的相同字段还是不同 DU 中具有相同名称的不同字段通常并不重要。只有当某种形式的代码重复出现过于频繁时,您才需要考虑另一种方法是否会更好。

      因此,在您的特定情况下,这不一定是一个好的解决方案,我假设项目种类和/或字段的数量可能不会那么有限。

      您只需要逐案判断。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-19
        • 2018-05-09
        • 2012-04-20
        • 1970-01-01
        • 2011-05-26
        • 1970-01-01
        • 1970-01-01
        • 2014-06-25
        相关资源
        最近更新 更多