2016-11-30 24 views
7

Я понимаю привлекательность чистых функциональных языков, таких как Haskell, где вы можете отслеживать побочные эффекты, такие как дисковый ввод-вывод, используя монад.Что считается побочным эффектом? Почему распределение памяти не является побочным эффектом?

Почему не все системные вызовы считаются побочными эффектами? Например, распределение памяти кучи (которое автоматически) в Haskell не отслеживается. И распределение стека может быть побочным эффектом, хотя я не уверен, что это было бы полезно. Оба они изменяют общее состояние системы.

Так где же линия, нарисованная для того, что является побочным эффектом, а что нет? Это просто то, что является самым «полезным»? Или есть более теоретическая основа?

+6

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

+3

Распределение памяти является побочным эффектом, если вы хотите контролировать, когда это произойдет. См. Обертки IORef/STRef/FunPtr. Просто, если это происходит автоматически, вы можете доверять своему компилятору, чтобы быть умным, поэтому Haskell не заставляет вас беспокоиться об этом. –

+0

@AlexisKing Как кто-то, кто иногда должен писать код для встроенных систем, это будет действительно интересный язык для просмотра. Я предполагаю, что это может быть написано как DSL в Haskell, но было бы круто, как автономный язык, который был составлен очень эффективно. – bheklilr

ответ

11

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

Язык программирования на самом деле не является реальной реализацией, поэтому, если вы не думаете о C og C++, который имеет распределение памяти и syscall как часть языка, языки более высокого уровня, где это обрабатывается системными примитивами, это не часть языка. Если это не часть языка, это не может быть побочным эффектом.

Теперь фактический код машинного кода реализации никогда не будет чистым, так как способ передачи аргументов и получения возвращаемых значений должен храниться либо в регистрах, либо в стеке, как путем мутации. Большинство концепций, которые мы используем во всех современных программах, преобразуются в арифметику, флаги, переходы и доступ к памяти. Каждая команда процессора, кроме NOP, мутирует машину. Программа, состоящая только из NOP, не очень полезна.

+1

Все хорошие ответы, я думаю, я смутил спецификацию для Haskell с ее реализацией. Благодарю. Теперь я задаюсь вопросом, существуют ли какие-либо низкоуровневые сборки/C-подобные языки, которые задают семантику побочных эффектов для таких вещей, как выделение. – relevate

+2

Оценка команд процессора также имеет аппаратную реализацию, поэтому NOP может (как бесполезно) сказать, что он изменил регистр указателя команд. –

+0

@thatotherguy Правда, но каждая инструкция помимо NOP также мутирует что-то еще, чем счетчик программ. – Sylwester

7

Ни распределение стека, ни распределение кучи - это то, что вы можете «делать» или наблюдать в Haskell. Поэтому его нельзя считать побочным эффектом. В некотором смысле, то же самое касается нагревания процессора, что, без сомнения, является узнаваемым физическим эффектом использования чистого кода Haskel.

Бывает так, что некоторые реализации Haskell на современном оборудовании и ОС будут выделять стек/кучу во время запуска вашего кода, но это не видно из вашего кода.

+0

«Так получилось, что некоторые реализации Haskell на современном оборудовании и ОС будут выделять стек/кучу во время запуска вашего кода» - и как! – jberryman