我有一个受歧视的工会,例如
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
绑定函数和用于解构的活动模式的附带模块。