Побочные эффекты в Scala

Я изучаю Scala прямо сейчас. Я немного знаком с Haskell, хотя не могу утверждать, что знаю его хорошо.

Примечание в скобках для тех, кто не знаком с Haskell

Одна черта, которая мне нравится в Haskell, заключается в том, что не только функции являются гражданами первого класса, но и побочные эффекты (позвольте мне называть их действиями). Действие, которое при выполнении наделит вас значением типа a, принадлежит определенному типу IO a. Вы можете передавать эти действия почти так же, как и любое другое значение, и комбинировать их интересными способами.

На самом деле, объединение побочных эффектов — это единственный способ в Haskell что-то с ними сделать, поскольку вы не можете их выполнить. Скорее, программа, которая будет выполнена, представляет собой комбинированное действие, возвращаемое вашей функцией main. Это ловкий трюк, который позволяет функциям быть чистыми, в то же время позволяя вашей программе делать что-то другое, кроме потребления энергии.

Основное преимущество этого подхода заключается в том, что компилятор знает о частях кода, в которых вы выполняете побочные эффекты, поэтому он может помочь вам отловить с ними ошибки.

Актуальный вопрос

Есть ли в Scala какой-то способ, чтобы компилятор проверял побочные эффекты для вас, чтобы, например, вы гарантированно не выполняли побочные эффекты внутри определенной функции?


person Andrea    schedule 23.07.2012    source источник
comment
Некоторое время я делал вводные замечания, как в публичной письменной форме, так и в собственных мыслях. Но я не знал их имени. Случайно ты дал мне образование. #проголосовать   -  person RichColours    schedule 17.06.2019


Ответы (2)


Нет, это в принципе невозможно в Scala, поскольку язык не обеспечивает ссылочную прозрачность — семантика языка не обращает внимания на побочные эффекты. Ваш компилятор не будет отслеживать и обеспечивать свободу от побочных эффектов за вас.

Вы сможете использовать систему типов для отметить некоторые действия как относящиеся к типу IO, и с дисциплиной программиста получить некоторую поддержку компилятора, но без проверки компилятором.

person Don Stewart    schedule 23.07.2012
comment
Спасибо, пост, на который вы ссылаетесь, выглядит очень интересно! Это именно то, что я искал. - person Andrea; 24.07.2012

Возможность обеспечения ссылочной прозрачности в значительной степени несовместима с целью Scala иметь систему классов/объектов, совместимую с Java.

Код Java может быть нечистым произвольным образом (и может быть недоступен для анализа при запуске компилятора Scala), поэтому компилятору Scala придется считать весь сторонний код нечистым (присваивая им тип IO). Чтобы реализовать чистый код Scala с вызовами Java, вам нужно было бы обернуть вызовы чем-то эквивалентным unsafePerformIO. Это добавляет шаблонность и делает интероперабельность гораздо менее приятной, но становится хуже.

Необходимость предполагать, что весь код Java находится в IO, если только программист не обещает иное, в значительной степени убьет наследование от классов Java. Предполагается, что все унаследованные методы относятся к типу IO; это было бы верно даже для интерфейсов, поскольку компилятор Scala должен был бы предположить существование нечистой реализации где-то в Java-земле. Таким образом, вы никогда не сможете получить класс Scala с какими-либо методами, отличными от IO, из класса или интерфейса Java.

Хуже того, даже для классов, определенных в Scala, теоретически может существовать неотслеживаемый подкласс, определенный в Java с нечистыми методами, экземпляры которого могут быть переданы обратно в Scala как экземпляры родительского класса. Поэтому, если компилятор Scala не может доказать, что данный объект не может быть экземпляром класса, определенного кодом Java, он должен предположить, что любой вызов метода для этого объекта может вызвать код, который был скомпилирован Компилятор Java без соблюдения законов того, что могут делать функции, возвращающие результаты не в IO. Это заставило бы почти все быть в IO. Но помещать все в IO в точности равносильно тому, чтобы ничего не помещать в IO и просто не отслеживать побочные эффекты!

Таким образом, Scala поощряет писать чистый код, но не пытается заставить вас это делать. Что касается компилятора, любой вызов чего-либо может иметь побочные эффекты.

person Ben    schedule 24.07.2012
comment
Это отличный ответ, но он принял ответ Дона за интригующую ссылку. - person Andrea; 24.07.2012