功能语言中的获取器和设置器


9

函数式编程的宗旨之一是使用纯函数。Pure函数是无副作用且参照透明的函数。

Getter并不是透明的-如果在两次Getter的调用之间调用了Setter,则即使Getter的参数没有(通常没有参数),它的返回值也会改变。

设置器会产生副作用-调用设置器通常会操纵不是其返回值的值(实际上,传统上,设置器不返回任何值)

我知道在Scala中,我们可以接受这样一个事实,即我们将两个范例(功能和面向对象)结合在一起,并像使用Java这样的语言时使用了getter / setter。

在像Haskell这样的语言(我不太会流利,但被告知对“纯”功能语言更真实)时,我很好奇,如何对对象的属性建模,以使Getters相对透明和Setters。有副作用吗?

解决方案是将调用设置器的对象的副本作为设置器的返回值传回,并且此副本包含对属性值的更改吗?


8
getter和setter会将对象作为参数(即使它通常是隐式的),因此,getters 参照透明的。

@delnan,仅当它正在读取的属性不可变时。
dan_waterworth 2011年

3
@dan_waterworth:仅当我们读取“相对透明”中的“相同”作为对象标识时。如果事实是基础属性不同,则使用不同的参数进行调用(这与大多数相等性定义一致)。这将忽略另一个调用setter的线程,并在对getter的调用与getter的finishing之间完成它,但是在那种情况下,您仍然遇到了更严重的问题。

Answers:


7

究竟。请参阅案例类方法copy或镜头的一般概念。

特别是,如果州需要更改,则可以使用州单子。可以通过镜头对状态monad进行更改,从而使从“状态”中提取信息并使更改变得容易。

又见这个问题,关于来自于深层结构,如“状态”并更改它的一般问题。如果您想更深入地了解,答案在镜片和拉链上都有很好的链接。


丹尼尔问题:将copy()绑定到Case类是否有任何特殊原因?这似乎并没有专门针对Case类的需求(错误的词,但不能想到另一个),在我看来,这似乎更适合所有类。如果我在非大小写类上需要copy()怎么办?我可以用来获得该功能的特征吗?
ThaDon 2011年

1
@ThaDon案例类应该由其构造函数参数定义-它们的相等性,哈希码和提取器均基于此假设,copy方法也是如此。在非大小写的类上,任何人都可以猜测构造器参数是否是复制类所需要的全部。但是,您可以轻松编写自己的复制方法。
Daniel C. Sobral

11

好吧,在Haskell中,对象(通常)是不可变的,因此getter(使用记录语法时会得到的)或充当getter的函数透明的。然后,您不必在对象上“设置”值-如果创建了对象,则该对象类似于旧对象,但是其中一个字段的值不同。这也是一个纯函数。


1
“对象(通常)是不可变的”,何时不是?
2016年

-1

“ Getters和Setters将该对象作为参数-尽管它通常是隐式的-因此,Getters是参照透明的。– delnan”

参照透明意味着函数始终为相同的输入返回相同的输出。因此,如果设置器更改了对象属性,则不会返回相同的输出。:)


但是,如果对象被设置器更改,则获取器的输入(即隐式自身参数)将发生更改。
斯蒂芬·斯蒂尔·斯蒂芬,

1
除非对象已在堆上移动,否则对象参考值/指针不会更改。
Casey Hawthorne

5
是的,但是从逻辑上讲,隐式输入是对象本身,而不是指针的值。
斯蒂芬·斯蒂尔·斯蒂尔

“如果某个对象的属性已被设置方法更改,则不会返回相同的输出”:从功能上讲,您已经破坏了第一个对象并创建了一个新的对象。出于性能原因(避免将引用从旧对象复制和更新到新对象),您正在将新对象存储在包含旧对象的同一存储区中。
Giorgio 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.