Roo*_*oxo 4 haskell types 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
} }
Run Code Online (Sandbox Code Playgroud)
有两个字段a
andb
和 ,在构造对象时,我通常只能访问其中一个字段,但另一个字段可以根据另一个字段进行计算。一个简单的例子是多边形,它要么被定义为点列表的凸包,要么被定义为线列表的交集(以及多面体的高维模拟)。b
计算起来可能会非常昂贵a
,因此我不想在创建对象时立即进行计算,而是等到实际需要时才进行计算。
我对此的一个想法是拥有一种记录类型
data P = {a:: Maybe A, b:: Maybe B}
makePA :: A -> P
-- ...
makePB :: B -> P
-- ...
Run Code Online (Sandbox Code Playgroud)
其中两者从ormakeP
创建一个。然后,每当我实际需要其中一个字段时,我都可以创建一个函数,类似于上面的函数,如果需要,它会计算该字段,然后返回两个字段都不再存在的新记录。但这似乎过于笨重,因为创建 a 需要一些计算(例如计算点的凸包),因此不能像通常那样创建记录。此外,我必须通过调用函数来封装其他函数中的每次使用,以确保实际计算值,然后访问该字段,我仍然必须确保是,而不是因为类型是。P
A
B
get
Nothing
P
P
get
Just A
Nothing
Maybe A
有更好的方法来解决这个问题吗?
lef*_*out 10
这容易多了。只需包含the和A
the B
,两者都不是可选的,并依赖于惰性 \xe2\x80\x93 它负责所有决定是否需要自动计算其中一个值。
data P = {a::A, b::B} \n\ncalculateBfromA :: A -> B\ncalculateAfromB :: B -> A\n\nmakePA :: A -> P\nmakePA a' = P a' (calculateBfromA a')\n\nmakePB :: B -> P\nmakePB b' = P (calculateAfromB b') b'\n
Run Code Online (Sandbox Code Playgroud)\n您可能会说,Haskell 实际上null
也像 Java 一样具有值,但它们始终与计算正确类型的正确值的方法相关联。Maybe
是为了null
实际上具有指称含义的值,但在您的示例中它们仅具有操作含义,Haskell 可以将其抽象掉。