Я не раз наблюдал это: человек описывает функциональный язык программирования (в отличие от языка программирования, в котором интенсивно используются вкрапленные состояния), этот человек скажет, что он очень математический, поэтому мы должны использовать язык математики; затем, чтобы продемонстрировать, начинается: «Допустим, у нас есть функция f, которая принимает входные данные x и выдает выходные данные y...» или что-то в этом роде.
Меня это раздражает, потому что я никогда не слышал, чтобы математик описывал функцию как принимающую входные данные и дающую выходные данные. Наоборот, я считаю, что функция рассматривается как карта, и можно сказать, что домен, карта и совместный домен существуют одновременно.
В мире компьютерной обработки определенная продолжительность времени обычно связана с операцией, но это не обязательно: может случиться так, что языковое представление на самом деле не представляет операцию напрямую (функция может даже быть полностью удалена оператором). компилятор кода или интерпретатор), или, возможно, функция на самом деле принимает какие-то другие входные данные, чем предполагалось, распределяется по многим процессорам и т. д. Короче говоря, машинные операции не обязательно представляются простым способом для интерпретации человеком языком программирования. .
Кроме того, время операции может быть незначительным, может выполняться параллельно с другой операцией или шаги программы могут выполняться в другой последовательности. Это может даже потребовать некоторых других более поздних операций, не очевидных для наблюдателя, поэтому может повлиять на другие моменты времени.
Однако я думаю, что возможен более фундаментальный конфликт. Как выразился Шопенгауэр в «Четырехкратном корне», существует проблема применения понятия «причинности» в физическом смысле к метафоре логической «причинности».
Компьютерная обработка, кажется, занимает промежуточное положение между «выводом как физической моделью» и «выводом как логической моделью». Является ли это фундаментальной проблемой, как я выразился? Возможно ли, что эти смешанные метафоры станут более проблематичными по мере развития области обработки данных?
Я не думаю, что мы на самом деле делаем что-то еще, кроме как используем разные слова для одного и того же. Если вы, например, посмотрите на функцию Haskellmod
по модулю:
mod :: a -> a -> a
Математически функция по модулю имеет вид Z × Z → N (где Z — множество целых чисел; N — множество натуральных чисел, неотрицательных целых чисел).
Вы можете увидеть то же самое в Haskell, за исключением того, что они не различают Z и N, что математически правильно, и что они используют только стрелки вместо × и стрелки.
В математике мы называем левую часть стрелки доменом, а правую — кодовым доменом; в функциональном программировании мы называем левые входы, а правые — выходы.
Использование слов «ввод» и «вывод» в контексте функционального языка программирования ужасно , потому что изменение ввода и вывода и функциональные языки основаны на идее, что вещи не меняются. Когда вы используете фактический ввод и вывод (вещи, которые меняются), вы используете язык таким образом, который больше не является строго функциональным, с использованием монад . Однако, когда кто-то понимает концепцию функционального языка, я не думаю, что использование «ввода» и «вывода» может принести больше вреда, чем вызвать некоторую путаницу.
Вы также говорите о разнице в том, что вычисления требуют времени. Функциональные языки иногда ленивы , а это означает, что они будут вычислять вещи только тогда, когда это необходимо. Например, мы можем поместить весь (бесконечный) набор натуральных чисел в список, пока вы не скажете ему вычислить все элементы (запросив сумму или что-то в этом роде). Эта концепция лени на самом деле очень похожа на то, что мы делаем в математике. Когда мы что-то доказываем, мы редко что-то вычисляем .
Сравнение физического вывода и логического вывода — хороший аргумент, особенно если учесть, что создание аппаратного обеспечения для функциональных языков — сложная задача . Исследования проводятся в университете Йорка, где разрабатывают Reduceron , но, насколько я знаю, это еще не тот уровень, на котором мы можем видеть, что машина полностью функциональна .
Возможно, но я не уверен, это (физический уровень против логического уровня) на самом деле является причиной того, что аппаратное обеспечение так сложно: мы пытаемся создать что-то, что принадлежит совершенно другому миру. Был ли Шопенгауэр, возможно, первым ученым-компьютерщиком? :)
Я не совсем осведомлен об ограничениях функциональных языков программирования, но теоретически возможно приказать ему вычислить что-то, для чего ему потребуется что-то бесконечное (будь то время или память), в то время как математика может сделать это без особых проблем.
Ленивый ответ: Да, все возможно
Хорошо, теперь более длинный ответ
Я думаю, что разница в формулировках между «вводом/выводом» и «отображением» используется из-за побочных эффектов. Математические отображения не имеют побочных эффектов, это просто отображения. Разница между значением 1 и вычислением сложного уравнения в точке, которая соответствует 1, не имеет значения, если только вы не хотите работать с уравнением явно.
Языки функционального программирования стараются избегать побочных эффектов, чтобы достичь аналогичной математической чистоты. Однако есть побочные эффекты, которых нельзя избежать, например потребление вычислительных ресурсов. Это заставляет людей мыслить менее математическими терминами. Во-первых, в каждом функциональном языке программирования есть по крайней мере одно процедурное понятие «вычислить», которое запускает процесс. Это маленькое ядро заставляет программистов мыслить немного иначе.
У функциональных программистов есть один веский аргумент: если мне нужно вычислить f(1, 2), ответ не изменится, если я вычислю f(1,2) и f(3, 4). Функциональный язык можно рассматривать как одновременное сосуществование всех значений по сравнению с процедурными языками, имеющими побочные эффекты, которые лишают нас возможности выполнять произвольный код.
Что касается метафор, которые становятся более проблематичными, это зависит от того, что вы считаете проблематичным. Учтите, что все метафоры во все времена были проблематичными, потому что метафоры работают именно так. Во всем мире нет области исследований, в которой не было бы экосистемы метафор, которые появляются, когда они полезны, и ослабевают, когда становятся менее полезными. Я полностью ожидаю, что эта модель сохранится и в вычислительной технике.
Уже есть отличные примеры мест, где метафоры не работают. Рассмотрим в мире процедурного программирования многопоточность. Долгое время мы могли использовать машину фон Неймана как метафору нашего настоящего компьютера. Однако с современными атомарными операциями мы вынуждены признать наличие кэшей памяти и других вещей, которые не фигурируют в метафоре. C++ только что выпустил новую спецификацию, включающую атомарные операции. 90 % обработки атомных характеристик в спецификации теперь относится к вещам, которые нельзя объяснить с помощью машины фон Неймана. Решение заключалось в том, что C++ изобрел новую метафору: модель памяти C++11, которая приближается к тому, что делает современное оборудование. Когда эта модель не сработает, мы изобретем новую.
В математике часто говорят, что функция принимает входные данные и дает выходные данные. Функция является более ограничительной концепцией, чем общее отношение между двумя доменами: она будет отображать только одно значение в выходном домене на каждое значение входного домена (это отношение «многие к одному»). Это также определенная характеристика функций в функциональном языке программирования. Математическая функция, строго говоря, не является функцией программирования, но, основываясь на этих сходствах, она является полезной абстракцией для обращения к последней (в отличие от императивных языков, где некоторые функции могут возвращать разные значения в разное время, например, когда они используют переменные состояния или внешние входы, такие как часы). В любом случае между математикой и алгоритмикой существует тесная связь. Оба имеют одинаковые логико-математические основы.
Программист может ожидать прямого соответствия между кодом и скомпилированной программой. Каждая реализованная операция будет выполняться как таковая. Возможно, они будут оптимизированы, но компилятор гарантирует, что результат будет таким же. В противном случае программы не были бы надежными. Другими словами, программист может надежно рассуждать, «как если бы» компьютер действительно считывал код во время выполнения и применял математические функции, как это сделал бы математик.
Оптимизация во время компиляции приводит к меньшей надежности по сравнению с ожидаемой длительностью (гарантируется только результат), но в большинстве случаев получение того же результата будет означать выполнение тех же операций, и оценка длительности на основе кода даст приблизительно хороший результат. Я думаю, что общая структура программы в целом отражена в скомпилированной программе.
В императивных языках программирования есть методы получения более точных показателей длительности во время выполнения, которые используются для профилирования (повышения эффективности программы). Я не знаю, существуют ли они для функциональных языков.
вирмайор
Джозеф Вайсман
вниз