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

5vf7fwbs  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(138)

给定以下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,在构造对象时,我通常只能访问其中一个,但另一个可以从另一个计算。一个简单的示例是定义为一列点的船体或一列线的交点的面从a计算b和从a计算b的开销可能相当大,因此我不想在创建对象时立即进行计算,而是等到实际需要时再进行计算。
我的一个想法是有一个记录类型

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

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

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

其中两个makePAB创建一个P。然后,每当我实际需要其中一个字段时,我可以创建一个get函数,类似于上面的函数,如果需要,它将计算该字段,然后返回两个字段都不再是Nothing的新记录。但这似乎过于笨拙,因为创建P需要进行一些计算(例如计算点的船体)并且因此不能像通常那样仅仅创建记录。此外,我必须通过调用get函数来将P的每次使用封装在其他函数中,我仍然需要确保它是Just A而不是Nothing,因为类型是Maybe A
有没有更好的办法来解决这个问题?

ffvjumwh

ffvjumwh1#

这要简单得多,只需包含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一样,但它们总是与一个方法相关联,以计算正确类型的正确值。Maybenull值,实际上有一个概念上的含义,但在你的例子中,它们只有一个操作上的含义,Haskell可以抽象掉。

相关问题