繁体   English   中英

函数式编程中具有缓存计算的数据类型

[英]Data Type with cached calculations in functional programming

鉴于以下 OOP 风格的示例代码,以纯功能风格获得此行为的好方法是什么,例如在 Haskell

class P{
  private A a;
  private B b;
 
  public P(A a'){
     this.a=a';
     this.b=null;
  }
 
 public P(B b'){
     this.a = null;
     this.b = b';
 }

 public A getA(){ 
    if(this.a==null){
       //code to calculate a from b
       this.a = result;
    }
   return this.a
 } 

 public B getB(){ 
    if(this.b==null){
       //code to calculate b from a
       this.b = result;
    }
   return this.b
 } }

有两个字段ab ,在构建 object 时,我通常只能访问其中一个,但另一个可以从另一个计算。 一个简单的例子是多边形,它要么被定义为点列表的凸包,要么被定义为线列表的交点(以及多面体的更高维模拟)。 a计算b可能会非常昂贵,反之亦然,因此我不想在创建 object 时立即进行计算,而是等到实际需要时再进行计算。

我对此的一个想法是有一个记录类型

data P = {a:: Maybe A, b:: Maybe B} 

makePA :: A -> P 
-- ...


makePB :: B -> P 
-- ...

其中两个makePAB创建一个P 然后,每当我真正需要其中一个字段时,我可以get function,类似于上面计算字段(如果需要),然后返回两个字段不再为Nothing的新记录。 但这似乎过于笨拙,因为创建P需要一些计算(例如计算点的凸包),因此不能像通常那样创建记录。 此外,我必须通过调用get函数来封装P在其他函数中的每次使用,以确保实际计算出该值,然后访问该字段,我仍然必须确保它是Just A而不是Nothing由于类型是Maybe A

有没有更好的方法来解决这个问题?

这要容易得多。 只需同时包含AB ,它们都不是可选的,并且依赖于惰性——它会自动处理所有决定是否需要计算的值。

data P = {a::A, b::B} 

calculateBfromA :: A -> B
calculateAfromB :: B -> A

makePA :: A -> P
makePA a' = P a' (calculateBfromA a')

makePB :: B -> P
makePB b' = P (calculateAfromB b') b'

你可以说,Haskell 实际上也有null值,就像 Java 一样,但它们总是与计算正确类型的正确值的方法相关联。 Maybe是针对实际上具有概念意义的null值,但在您的示例中,它们仅具有操作意义, Haskell 可以抽象掉。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM