Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

One of the tenets of Functional Programming is the use of Pure Functions. A Pure function is one that is side-effect free and referentially transparent.

Getters are not referentially transparent - if a Setter is called between calls to the Getter, the Getter's return value changes even though its parameters have not (typically no parameters)

Setters produce side-effects - Calling a Setter typically manipulates a value that is not its return value (in fact, traditionally a setter returns nothing)

I know in Scala we just kind accept the fact we are meshing together two paradigms (functional and object oriented) and use getters/setters as we would in a language like Java.

In a language like Haskell (which I'm not fluent with, but I'm told holds truer to a "Pure" functional language) I'm just curious, how you would model properties on objects such that Getters are referentially transparent and Setters are side-effect free?

Would the solution be to pass back a copy of the object the setter was invoked on as the setter's return value, and this copy contains the change to the property value?

share|improve this question
7  
Getters and setters have the object as parameter - even though it's usually implicit - so getters are referentially transparent. –  delnan Jul 27 '11 at 18:21
    
@delnan, only if the attribute that it is reading is immutable. –  dan_waterworth Jul 28 '11 at 7:53
3  
@dan_waterworth: Only if we read the "same" in "referentially transparent" as object identity. If the fact the underlying attribute is different makes it a call with different arguments (which is in line with most definitions of equality). This is ignoring another thread calling a setter and finishing it between the call to the getter and the getter finishing, but in that case you got more serious problems anyway. –  delnan Jul 28 '11 at 8:48
add comment

3 Answers

up vote 7 down vote accepted

Exactly. See case class method copy, or the general concept of lenses.

In particular, if state needs changing, you'd use a State monad. Changes to that state monad can be made through lenses, which makes extracting information from "state" and changing it easy.

See also this question about the general problem that comes from a deep structure like "state" and making changes to it. The answers have good links on both lenses and zippers if you want to get deeper into that.

share|improve this answer
    
Question Daniel: is there any particular reason that copy() is tied to Case classes? This doesn't seem specific to the needs (wrong word, but can't think of another) of Case classes specifically, it seems (to me) more of a feature suitable for all classes. What if I need copy() on my non-case class? Is there a trait I can use to get that functionality? –  ThaDon Jul 28 '11 at 2:11
1  
@ThaDon case classes are supposed to be defined by their constructor parameters -- their equality, hash code and extractor are based on this assumption, and so is the copy method. On non-case classes, it is anyone's guess whether the constructor parameters are all that's needed to copy a class. You can, however, easily write your own copy method. –  Daniel C. Sobral Jul 28 '11 at 14:07
add comment

"Getters and setters have the object as parameter - even though it's usually implicit - so getters are referentially transparent. – delnan"

Referentially transparent means that the function ALWAYS returns the same output for the same inputs; so if an object attribute has been changed by a setter, you are not returning the same output. :)

share|improve this answer
    
But, if the object was changed by a setter, the input to the getter (i.e. the implicit self argument) HAS changed. –  Stephen C. Steel Jul 27 '11 at 21:02
1  
The object reference value/pointer hasn't changed unless the object has been moved on the heap. –  Casey Hawthorne Jul 27 '11 at 23:05
5  
Yes, but logically, the implicit input is the object itself, not the value of the pointer. –  Stephen C. Steel Jul 28 '11 at 3:54
    
"if an object attribute has been changed by a setter, you are not returning the same output": In functional terms, you have destroyed the first object and created a new one. For performance reasons (avoid copying and updating of references from the old to the new object) you are storing the new object in the same memory area that contained the old object. –  Giorgio Jun 17 '13 at 5:21
add comment

Well, in Haskell, objects are (usually) immutable, so getters (which you get when you use record syntax) or functions that act like getters are referentially transparent. And then you don't "set" values on objects -- if anything you create a new object which is similar to the old one, but with a different value for one of the fields. This is also a pure function.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.