Подтвердить что ты не робот

Что означает термин "разум" в информатике?

Во время обучения функциональному программированию я продолжаю понимать термин "причина", особенно в контексте чистых функций и/или ссылочной прозрачности. Может кто-нибудь объяснить, что именно это означает?

4b9b3361

Ответ 1

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

Примеры таких свойств включают:

  • правильность (делает ли программа то, что она должна)
  • производительность (сколько займет времени)
  • масштабируемость (как влияет производительность на вход)
  • безопасность (может ли алгоритм быть неправильно использован)

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


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


В качестве примера можно привести некоторые примеры того, как можно рассуждать о некоторых из этих вещей и как можно сделать эмпирическое наблюдение:

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

Производительность и масштабируемость. Мы можем анализировать наш код и доказывать границы производительности алгоритма, чтобы мы знали, как время, затрачиваемое на это, зависит от размера ввода. Эмпирически мы можем сравнить наш код и посмотреть, как быстро он работает на конкретной машине. Мы можем выполнить нагрузочное тестирование и увидеть, сколько фактического ввода может выполнить наш машинный/алгоритм, прежде чем он скроется/станет непрактичным.

Ответ 2

Рассуждение о коде, в самом расплывчатом смысле слова, означает думать о вашем коде и о том, что он на самом деле делает (не то, что вы думаете, что он должен делать). Это означает

  • осознавая , как ваш код ведет себя, когда вы бросаете на него данные,
  • зная , что вы можете реорганизовать, не нарушая его, и
  • сохранение вкладок , какие оптимизации могут быть выполнены,

между прочим. Для меня аргументированная часть играет самую большую роль, когда я отлаживаю или рефакторинг.

Чтобы использовать приведенный вами пример: ссылочная прозрачность помогает мне, когда я пытаюсь понять, что неправильно с функцией. Референциальная прозрачность гарантирует, что, когда я выхожу с функцией, давая ей разные аргументы, я знаю, что функция будет реагировать так же, как внутри моей программы. Это не зависит ни от чего, кроме его аргументов. Это облегчает объяснение функции - в отличие от императивного языка, где функция может зависеть от некоторой внешней переменной, которая может меняться под моим носом.

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

map f (map g xs) === map (f . g) xs

Это полезное свойство, которое я могу применить непосредственно, когда я рефакторинг. Тот факт, что я могу указать такие свойства кода Haskell, облегчает рассуждение. Я мог бы попытаться сформулировать это свойство в программе Python, но я был бы гораздо, гораздо менее уверен в этом, потому что, если мне не повезло в выборе f и g, результаты могут сильно отличаться.

Ответ 3

Неформально это означает: "Возможность рассказать, что программа будет делать, просто просмотрев код". Это может быть удивительно сложно на большинстве языков из-за побочных эффектов, кастинга, неявных преобразований, перегруженных функций и операторов и т.д. Т.е., когда вы не можете рассуждать о коде, используя только ваш мозг, вам нужно запустить его, чтобы увидеть, что он будет делать для заданного ввода.

Ответ 4

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

Эти свойства могут быть очень простыми. Например, учитывая следующее определение (.) и id:

id :: a -> a
id x = x

(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) = \x -> f (g x)

... мы могли бы затем доказать, что:

f . id = f

Это легко доказать, потому что:

(f . id) = \x -> f (id x) = \x -> f x = f

Обратите внимание, как я доказал это для all f. Это означает, что я знаю, что это свойство всегда истинно, несмотря ни на что, поэтому мне больше не нужно проверять это свойство в каком-то пакете unit test, потому что я знаю, что он никогда не может потерпеть неудачу.

Ответ 5

"Рассуждение о программе" - это просто "анализ программы, чтобы увидеть, что она делает".

Идея заключается в том, что чистота упрощает понимание, как человеком, изменяющим программу, так и машиной, компилирующей программу или анализируя ее для разбитых угловых случаев.