给定以下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
} }
有两个字段a
和b
,在构造对象时,我通常只能访问其中一个,但另一个可以从另一个计算。一个简单的示例是定义为一列点的船体或一列线的交点的面从a
计算b
和从a
计算b
的开销可能相当大,因此我不想在创建对象时立即进行计算,而是等到实际需要时再进行计算。
我的一个想法是有一个记录类型
data P = {a:: Maybe A, b:: Maybe B}
makePA :: A -> P
-- ...
makePB :: B -> P
-- ...
其中两个makeP
从A
或B
创建一个P
。然后,每当我实际需要其中一个字段时,我可以创建一个get
函数,类似于上面的函数,如果需要,它将计算该字段,然后返回两个字段都不再是Nothing
的新记录。但这似乎过于笨拙,因为创建P
需要进行一些计算(例如计算点的船体)并且因此不能像通常那样仅仅创建记录。此外,我必须通过调用get
函数来将P
的每次使用封装在其他函数中,我仍然需要确保它是Just A
而不是Nothing
,因为类型是Maybe A
。
有没有更好的办法来解决这个问题?
1条答案
按热度按时间ffvjumwh1#
这要简单得多,只需包含
A
和B
,两者都不是可选的,并依赖于惰性-它负责所有的决定-是否-其中一个值-需要被自动计算。你可以说,Haskell实际上也有
null
值,就像Java一样,但它们总是与一个方法相关联,以计算正确类型的正确值。Maybe
是null
值,实际上有一个概念上的含义,但在你的例子中,它们只有一个操作上的含义,Haskell可以抽象掉。