Геттеры и сеттеры на функциональных языках

9

Одним из принципов функционального программирования является использование чистых функций. Функция Pure - это функция, которая не имеет побочных эффектов и прозрачна по ссылкам.

Получатели не являются ссылочно прозрачными - если метод вызова вызывается между вызовами метода получения, возвращаемое значение метода получения изменяется, даже если его параметры не изменяются (как правило, параметров нет)

Сеттеры вызывают побочные эффекты. Вызов сеттера обычно манипулирует значением, которое не является его возвращаемым значением (фактически, обычно сеттер ничего не возвращает)

Я знаю, что в Scala мы просто любезно принимаем тот факт, что мы объединяем две парадигмы (функциональную и объектно-ориентированную) и используем геттеры / сеттеры, как в языке, подобном Java.

В таком языке, как Haskell (с которым я не бегло говорю, но мне говорят, что это более справедливо по отношению к «чистому» функциональному языку), мне просто любопытно, как бы вы смоделировали свойства объектов таким образом, чтобы Getters были ссылочно прозрачными и Setters Побочные эффекты свободны?

Будет ли решение возвращать копию объекта, для которого вызывался установщик, в качестве возвращаемого значения установщика, и эта копия содержит изменение значения свойства?

ThaDon
источник
8
Методы получения и установки имеют объект в качестве параметра - хотя он обычно неявный - поэтому методы получения являются прозрачными по ссылкам.
@delnan, только если атрибут, который он читает, является неизменным.
dan_waterworth
3
@dan_waterworth: Только если мы читаем "то же самое" в "ссылочно-прозрачном" как идентификатор объекта. Если факт, лежащий в основе атрибута отличается, делает его вызовом с другими аргументами (что соответствует большинству определений равенства). Это игнорирование другого потока, вызывающего установщик и заканчивающего его между вызовом получателя и завершением получателя, но в этом случае у вас все равно возникли более серьезные проблемы.

Ответы:

7

Точно. Смотрите метод case case copyили общую концепцию линз.

В частности, если нужно изменить штат, вы бы использовали монаду штата. Изменения в монаду этого состояния можно вносить с помощью линз, что облегчает извлечение информации из «состояния» и ее изменение.

См. Также этот вопрос об общей проблеме, которая исходит от такой глубокой структуры, как «состояние» и внесение в нее изменений. Ответы содержат хорошие ссылки на линзы и молнии, если вы хотите углубиться в это.

Даниэль С. Собрал
источник
Вопрос Даниэль: есть ли особая причина, по которой copy () связана с классами Case? Это не кажется специфическим для потребностей (неправильное слово, но не могу придумать другого) классов Case, в частности, мне кажется (больше) особенность, подходящая для всех классов. Что делать, если мне нужно copy () в моем не-case классе? Есть ли черта, которую я могу использовать, чтобы получить эту функциональность?
ThaDon
1
Классы дел @ThaDon должны определяться параметрами их конструктора - их равенство, хеш-код и экстрактор основаны на этом предположении, как и метод copy. На не-case классах можно догадаться, являются ли параметры конструктора всем необходимым для копирования класса. Однако вы можете легко написать свой собственный метод копирования.
Даниэль С. Собрал,
11

Что ж, в Haskell объекты (как правило) являются неизменяемыми, поэтому методы получения (которые вы получаете при использовании синтаксиса записи) или функции, которые действуют как методы получения, являются прозрачными по ссылкам. И тогда вы не «устанавливаете» значения для объектов - если что-то создаете новый объект, который похож на старый, но с другим значением для одного из полей. Это тоже чистая функция.

MatrixFrog
источник
1
«объекты (обычно) неизменны», когда они не являются?
Сара
-1

«Получатели и установщики имеют объект в качестве параметра - даже если он обычно неявный - так что получатели являются ссылочно прозрачными. - delnan»

Прозрачная ссылка означает, что функция ВСЕГДА возвращает одинаковые выходные данные для одних и тех же входных данных; поэтому, если атрибут объекта был изменен установщиком, вы не возвращаете тот же результат. :)

Кейси Хоторн
источник
Но если объект был изменен установщиком, входные данные получателя (то есть неявный аргумент self) изменились.
Стивен С. Сталь
1
Ссылочное значение объекта / указатель не изменились, если объект не был перемещен в куче.
Кейси Хоторн
5
Да, но логически, неявный ввод - это сам объект, а не значение указателя.
Стивен С. Сталь
«если атрибут объекта был изменен установщиком, вы не возвращаете тот же результат»: с функциональной точки зрения вы уничтожили первый объект и создали новый. По соображениям производительности (избегайте копирования и обновления ссылок со старого на новый объект) вы сохраняете новый объект в той же области памяти, где содержался старый объект.
Джорджио