Возвращает ли случайное значение из функции побочный эффект? - PullRequest
6 голосов
/ 08 декабря 2010

Я работал над кодом F # и работал над функцией, возвращающей случайную строку из набора строк.Допустим, у меня было что-то вроде этого:

open System

let a = [|"a";"b";"c";"d"|]

let rstring (arr:string[]) =
   let r = new Random()
   arr.[r.Next(0,3)]

let resultstring = rstring a;;

Мой вопрос таков: мое понимание понятия функционального программирования состоит в том, что если данная функция имеет один и тот же вход каждый раз, она всегда должна возвращать один и тот же результат.Таким образом, в данном конкретном случае каждый раз возвращается другая строка «побочный эффект»?Мне просто любопытно.

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


РЕДАКТИРОВАТЬ: Спасибо за всю информацию всем.Похоже, что я соединил понятия ссылочной прозрачности и отсутствия побочных эффектов.Итак, спасибо всем, что объяснили мне разницу, и спасибо за ваши ответы.

Ответы [ 5 ]

13 голосов
/ 08 декабря 2010

Да.

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

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

7 голосов
/ 08 декабря 2010

«Побочный эффект» означает, что функция изменяет некоторое состояние, а не то, что возвращаемое значение отличается.В вашем случае функция выполняет оба действия - она ​​изменяет состояние PRNG и возвращает другое значение.

Редактировать:

Я также добавлю, что если функция всегда возвращаетТо же значение для данного входа называется идемпотентом.Также «побочный эффект» включает функции, которые читают из внешнего состояния.Например:

int global = 0;
int function()
{
  return global;
}

имеет побочные эффекты.

3 голосов
/ 08 декабря 2010

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

2 голосов
/ 09 декабря 2010

Игнорирование деталей реализации генератора случайных чисел (что на практике требует побочных эффектов, а в теории нет необходимости), тогда эта функция не имеет побочных эффектов, но не является чистой.

По сути, представьте, что вызов функции - это машина оракула, которая возвращает случайные числа, полностью основанные на ничто. Где-то есть доказательство того, что вы не можете этого сделать, но пока только представьте, что это так.

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

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

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

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

http://fsharpcode.blogspot.com/2008/12/f-state-monad-type-state-state-state-of.html

В общем, возьмите это, сделайте так, чтобы вы указали генератор случайных чисел и 'a int, и тогда ваш поток управления изолирует примесь от одной функции и создаст жесткий порядок для секвенирования.

На самом деле нет смысла делать это в F #, поскольку наличие нечистых функций на самом деле не вызывает проблем (с другой стороны, наличие функций с побочными эффектами).

Конечно, эта монада нечиста, но она хорошо изолирует нечистоту.

1 голос
/ 08 декабря 2010

Не думаю, что ваш пример будет рассматриваться как побочный эффект.

http://en.wikipedia.org/wiki/Side_effect_(computer_science)

...