Функциональное программирование и нефункциональное программирование

StackOverflow https://stackoverflow.com/questions/24279

Вопрос

На моем втором курсе университета нас "учили" Haskell, я почти ничего не знаю о нем и еще меньше о функциональном программировании.

Что такое функциональное программирование, почему и / xor, где я хотел бы использовать его вместо нефункционального программирования, и прав ли я, полагая, что C - это нефункциональный язык программирования?

Это было полезно?

Решение

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

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

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

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

Другие советы

Что такое функциональное программирование

Сегодня широко используются два различных определения термина "функциональное программирование":

Более старое определение (происходящее из Lisp) заключается в том, что функциональное программирование - это программирование с использованием функций первого класса, т.е.где функции обрабатываются как любое другое значение, поэтому вы можете передавать функции в качестве аргументов другим функциям, а функция может возвращать функции среди их возвращаемых значений.Кульминацией этого является использование функций более высокого порядка, таких как map и reduce (возможно, вы слышали о mapReduce как отдельная операция, широко используемая Google и, что неудивительно, являющаяся ее близким родственником!).Типы .NET System.Func и System.Action сделайте функции более высокого порядка доступными в C #.Хотя каррирование непрактично в C #, функции, которые принимают другие функции в качестве аргументов, являются общими, напримертот самый Parallel.For функция.

Более молодое определение (популяризированное Haskell) заключается в том, что функциональное программирование также сводит к минимуму и контролирует побочные эффекты, включая мутацию, т.е.написание программ, которые решают задачи путем составления выражений.Это чаще называют "чисто функциональным программированием".Это становится возможным благодаря совершенно разным подходам к структурам данных, называемым "чисто функциональными структурами данных".Одна из проблем заключается в том, что перевод традиционных императивных алгоритмов на использование чисто функциональных структур данных обычно снижает производительность в 10 раз.Haskell - единственный сохранившийся чисто функциональный язык программирования, но эти концепции проникли в основное программирование с помощью таких библиотек, как Linq в сети.

где бы я хотел использовать его вместо нефункционального программирования

Повсюду.Лямбды в C # теперь продемонстрировали основные преимущества.В C ++ 11 есть лямбды.Сейчас нет никаких оправданий для того, чтобы не использовать функции более высокого порядка.Если вы можете использовать такой язык, как F #, вы также получите выгоду от вывода типов, автоматического обобщения, карринга и частичного применения (а также множества других языковых функций!).

прав ли я, полагая, что C - это нефункциональный язык программирования?

ДА.C - это процедурный язык.Однако вы можете получить некоторые преимущества функционального программирования, используя указатели на функции и void * в C.

Возможно, стоит ознакомиться с этой статьей о F# "101" недавно опубликованный журнал CoDe Mag.

Также, У Дастина Кэмпбелла отличный блог где он опубликовал много статей о своих приключениях по освоению F #..

Я надеюсь, вы найдете это полезным :)

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

Кроме того, просто для того, чтобы добавить, мое понимание функционального программирования заключается в том, что все является функцией или параметрами функции, а не экземплярами / объектами с сохранением состояния..Но я могу ошибаться, F # - это то, чем я до смерти хочу заняться, но просто у меня нет времени!:)

Пример кода Джона Статистика не показывает функциональное программирование, потому что, когда вы занимаетесь функциональным программированием, ключевым моментом является то, что код не выполняет НАЗНАЧЕНИЙ ( record = thingConstructor(t) является заданием), и у него нет ПОБОЧНЫХ ЭФФЕКТОВ (localMap.put(record) это утверждение с побочным эффектом).В результате этих двух ограничений все, что функция does полностью фиксируется его аргументами и возвращаемым значением.Перепишите код статистика так, как он должен был бы выглядеть, если бы вы хотели эмулировать функциональный язык с использованием C ++:

RT getOrCreate(const T thing, 
                  const Function<RT<T>> thingConstructor, 
                  const Map<T,RT<T>> localMap) {
    return localMap.contains(t) ?
        localMap.get(t) :
        localMap.put(t,thingConstructor(t));
}

В результате правила отсутствия побочных эффектов каждый оператор является частью возвращаемого значения (следовательно return приходит Первый), и каждое утверждение является выражением.В языках, реализующих функциональное программирование, return ключевое слово подразумевается, и если оператор ведет себя как C ++ ?: оператор.

Кроме того, все является неизменяемым, так что localMap.put должен создать новую копию Локальная карта и верните его, вместо того чтобы изменять оригинал Локальная карта, как это сделала бы обычная программа на C ++ или Java.В зависимости от структуры localMap копия может повторно использовать указатели на оригинал, уменьшая объем данных, которые необходимо скопировать.

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

Однако функциональные программы, как правило, выполняются медленно (из-за всего того, что им приходится выполнять копирование), и они, как правило, плохо взаимодействуют с другими программами, процессами операционной системы или операционными системами, которые имеют дело с адресами памяти, блоками байтов младшего порядка и другими специфичными для компьютера нефункциональными битами.Степень невзаимозамещаемости, как правило, обратно пропорциональна степени функциональной чистоты и строгости системы типов.

Более популярные функциональные языки имеют очень, очень строгие системы типов.В OCAML вы даже не можете смешивать математику целых чисел и чисел с плавающей запятой или использовать одни и те же операторы (+ - для добавления целых чисел, +.предназначен для добавления значений с плавающей точкой).Это может быть как преимуществом, так и недостатком, в зависимости от того, насколько высоко вы цените способность средства проверки типов выявлять определенные виды ошибок.

Функциональные языки также, как правило, имеют действительно большие среды выполнения.Haskell является исключением (исполняемые файлы GHC почти такие же маленькие, как программы на C, как во время компиляции, так и во время выполнения), но SML, Common Lisp и Scheme-программам всегда требуются тонны памяти.

Да, вы правы, полагая, что C - нефункциональный язык.C - это процедурный язык.

Я предпочитаю использовать функциональное программирование, чтобы избавить себя от повторной работы, создав более абстрактную версию, а затем используя ее вместо этого.Позвольте мне привести пример.В Java я часто ловлю себя на том, что создаю карты для записи структур и, таким образом, пишу структуры getOrCreate.

SomeKindOfRecord<T> getOrCreate(T thing) { 
    if(localMap.contains(t)) { return localMap.get(t); }
    SomeKindOfRecord<T> record = new SomeKindOfRecord<T>(t);
    localMap = localMap.put(t,record);
    return record; 
}

Это случается очень часто.Теперь на функциональном языке я мог бы написать

RT<T> getOrCreate(T thing, 
                  Function<RT<T>> thingConstructor, 
                  Map<T,RT<T>> localMap) {
    if(localMap.contains(t)) { return localMap.get(t); }
    RT<T> record = thingConstructor(t);
    localMap = localMap.put(t,record);
    return record; 
}

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

getOrCreate = myLib.getOrCreate(*,
                                SomeKindOfRecord<T>.constructor(<T>), 
                                localMap);

(где * - это своего рода обозначение "оставьте этот параметр открытым", которое является своего рода каррированием)

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

Если вы ищете хороший текст на F#

Эксперт F# автор сценария - Дон Сайм в соавторстве.Создатель F#.Он работал над дженериками в .NET специально для того, чтобы иметь возможность создавать F #.

F # смоделирован по образцу OCaml, поэтому любой текст OCaml также поможет вам выучить F #.

Я нахожу Что такое функциональное программирование? быть полезным

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

Предпочитаю явные when параметр

public Program getProgramAt(TVGuide guide, int channel, Date when) {
  Schedule schedule = guide.getSchedule(channel);

  Program program = schedule.programAt(when);

  return program;
}

закончился

public Program getCurrentProgram(TVGuide guide, int channel) {
  Schedule schedule = guide.getSchedule(channel);

  Program current = schedule.programAt(new Date());

  return current;
}

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top