F#相当于Scala lazy val与case class / discriminated union

时间:2015-02-12 13:55:49

标签: f# lazy-evaluation lazy-initialization

在Scala我可以这样做:

abstract class MyData
case class A() extends MyData
case class B() extends MyData

implicit class HeavyComputationProvider(val data : MyData) {
    private def _HeavyComputation() = /* */;
    lazy val HeavyComputation = this._HeavyComputation();
}

// Example usage:
val a = A
println a.HeavyComputation // This will calculate
println a.HeavyComputation // This will use the cached value

这有利于重新使用时的缓存,但不使用时不计算。

如何为以下F#类型提供惰性HeavyComputation

type MyData =
    | A
    | B

type MyData with
    member private this.__HeavyComputation = (* *)

    // Error: This declaration element is not permitted in an augmentation and this is unavailable
    let _HeavyComputation = lazy((* *))
    // This will just create a *new* lazy computation each time
    member this._HeavyComputation = lazy(this.__HeavyComputation)
    // This should lazily compute & cache, transparent to the caller
    member this.HeavyComputation = this._HeavyComputation.Force

1 个答案:

答案 0 :(得分:2)

我认为Scala方法没有直接的等价物。这样做需要将一些额外的状态保留为对象的一部分(例如,惰性值),并且F#不允许在对象定义后向对象添加其他状态。

您可以做的最接近的事情是编写一个包装类型,将原始MyData值与其他延迟计算一起存储:

type MyData =
    | A
    | B

type MyDataWithComputation(data:MyData) =
  let _HeavyComputation = lazy(1)
  member this.MyData = data
  member this.HeavyComputation = _HeavyComputation.Value

然后按如下方式使用它:

let myd = MyDataWithComputation(A)
myd.HeavyComputation 
myd.HeavyComputation