我有一个受歧视的工会,例如

type Dish =
| Eggs
| Spam of Dish


这基本上是一个链表,没有任何内容,例如Spam(Spam(Spam(Eggs)))。我想严格地对这种结构进行计算,例如计算长度,并记住结果。在普通类型中,我将使用本地类let绑定,但在有区别的联合中不可用。

一种方法是

type Count = int
type Dish =
| Eggs
| Spam of Dish * Count


但是,当我需要的数据可以轻松计算时,这确实很麻烦,但是我仍然希望有更好的方法(无需使用外部可变结构)。

最佳答案

一种选择是将联合用例设置为私有以隐藏缓存的长度。

//the 'guts' of Dish -- entirely hidden
type private DishImpl =
  | Eggs
  | Spam of DishImpl

// Dish wrapper type -- implementation hidden
type Dish =
  private
  | Dish of DishImpl * int
  with
    // O(1), just get the 'length' field
    member x.Length = let (Dish(_, len)) = x in len
    static member Eggs() = Dish(Eggs, 1)
    static member Spam(Dish(dish, len)) = Dish(Spam dish, len + 1)

let eggs = Dish.Eggs()
let spam = Dish.Spam(eggs)
printfn "%d" eggs.Length //outputs: 1
printfn "%d" spam.Length //outputs: 2


要正确执行此操作,请创建一个带有let绑定函数和用于解构的活动模式的附带模块。

09-11 17:18