ventajas programacion orientada objetos logicos lenguajes imperativa funcional ejemplos desventajas haskell functional-programming

haskell - logicos - programacion funcional vs orientada a objetos



¿Cuáles son algunos de los problemas mejores/peor abordados por la programación funcional? (11)

A menudo he escuchado que la programación funcional resuelve muchos problemas que son difíciles en la programación procedimental / imperativa. Pero también he escuchado que no es bueno en algunos otros problemas que la programación de procedimientos es simplemente genial.

Antes de abrir mi libro sobre Haskell y bucear en la programación funcional, me gustaría al menos una idea básica de para qué puedo usarlo realmente (fuera de los ejemplos del libro). Entonces, ¿cuáles son esas cosas en las que sobresale la programación funcional? ¿Cuáles son los problemas para los que no es adecuado?

Actualizar

Tengo buenas respuestas sobre esto hasta ahora. No puedo esperar para empezar a aprender Haskell ahora. Solo tengo que esperar hasta que domine C :)

Razones por las cuales la programación funcional es excelente:

  • Muy conciso y sucinto: puede expresar ideas complejas en declaraciones breves y discretas.
  • Es más fácil de verificar que los lenguajes imperativos, bueno donde la seguridad en un sistema es crítica.
  • La pureza de las funciones y la inmutabilidad de los datos hace que la programación simultánea sea más plausible.
  • Muy adecuado para escribir y escribir compiladores (aunque me gustaría saber por qué).
  • Los problemas relacionados con las matemáticas se resuelven de manera sencilla y hermosa.

Áreas donde la programación funcional lucha:

  • Debatable : aplicaciones web (aunque supongo que esto dependería de la aplicación).
  • Aplicaciones de escritorio (aunque depende del idioma probablemente, F # sería bueno en este caso, ¿no?).
  • Cualquier cosa donde el rendimiento sea crítico, como los motores de los juegos.
  • Cualquier cosa que involucre un montón de estado del programa.

Algunos problemas me parecen adecuados para la programación funcional:

  • concurrencia
  • compiladores
  • scripting

Los problemas que personalmente encuentro no son tan adecuados:

  • aplicaciones web (pero probablemente solo soy yo, Hacker News, por ejemplo, se implementa en LISP)
  • aplicaciones de escritorio
  • motores de juego
  • cosas por las que pasas mucho estado

Considero que la simplicidad de la programación funcional para los problemas matemáticos con la matriz matemática es absolutamente hermosa, eche un vistazo a cómo se resuelven estos tipos de problemas en Scheme.


El paradigma funcional y orientado a objetos tiene fuerza ortogonal. se podría decir que la programación funcional tiene énfasis en los verbos y la programación orientada a objetos en sustantivos. O, en términos más prácticos: la orientación de los objetos hace que agregar nuevos datos sea sencillo, mientras que la programación funcional hace que agregar nuevas herramientas sea simple. Ambos requieren cambios en el código para lograr el otro objetivo. Le gustaría leer http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.18.4525&rep=rep1&type=pdf (Sintetizar el diseño orientado a objetos y funcional para promover la reutilización


En realidad, me gusta usar código funcional puro para problemas que requieren administrar mucho estado. Esos idiomas poco comunes tienden a proporcionar los mejores mecanismos para el manejo explícito del estado, ya que no te permiten hacerlo implícitamente. Administrar implícitamente el estado puede parecer más fácil a pequeña escala, pero una vez que el estado comienza a ser complejo, se encuentra con problemas sin las garantías de corrección que tiene al hacerlo de manera FP.


Encuentro que Haskell es adecuado para hacer cualquier cosa relacionada con las matemáticas. No es que sea un proyecto profesional real, pero hice un solucionador de sudoku y un analizador de poker con él. Tener un programa que sea matemáticamente demostrable es genial.

En cuanto a lo que no es adecuado para nada es cualquier cosa donde el rendimiento es una prioridad. Usted tiene menos control sobre los algoritmos utilizados, ya que es más declarativo que imperativo.


La programación funcional sería buena para la programación paralela. El hecho de que no confíe en los cambios de estado con programación funcional significa que los diversos procesadores / núcleos no pisarán entre sí. Por lo tanto, los tipos de algoritmos que se combinan bien con el paralelismo, como la compresión, los efectos gráficos y algunas tareas matemáticas complejas, también suelen ser buenos candidatos para la programación funcional. Y el hecho de que las CPU multi-core y las GPU solo estén creciendo en popularidad también significa que la demanda de este tipo de cosas crecerá.


La programación funcional sobresale en la concisión, debido a la existencia de funciones de nivel superior (mapa, lfold, grep) y tipo de inferencia .

También es excelente en la programación genérica , por las mismas razones, y eso aumenta aún más la capacidad de expresar ideas complejas en una breve declaración sin ofuscación.

Aprecio estas propiedades ya que hacen plausible la programación interactiva . (por ejemplo, R , SML ).

Sospecho que la programación funcional también se puede verificar más fácilmente que otros enfoques de programación, lo que es ventajoso en sistemas críticos de seguridad (Centrales Nucleares y Dispositivos Médicos).


No estoy de acuerdo con que FP no se pueda usar para aplicaciones web. Sé que Paul Grahm y Robert Morris comenzaron Viaweb que usaba Lisp para entregar aplicaciones web. Creo que a medida que te acercas al hardware (controladores de dispositivo, kernel, etc.), uno quiere usar un lenguaje de bajo nivel como sea posible. Esto se debe a que si se usan más abstracciones, es más difícil depurarlas en caso de errores. Eche un vistazo al artículo "La ley de la abstracción lefal" de Joel Spolsky.


Puede que no esté directamente relacionado con la programación funcional, pero nada supera a los sindicatos en el diseño y la implementación de las estructuras de datos. Comparemos dos piezas equivalentes de código:

F#:

type ''a stack = Cons of ''a * stack | Nil let rec to_seq = function | Nil -> Seq.empty; | Cons(hd, tl) -> seq { yield hd; yield! to_seq tl } let rec append x y = match x with | Nil -> y | Cons(hd, tl) -> Cons(hd, append tl y) let x = Cons(1, Cons(2, Cons(3, Cons(4, Nil)))) let y = Cons(5, Cons(6, Cons(7, Cons(8, Nil)))) let z = append x y to_seq z |> Seq.iter (fun x -> printfn "%i" x)

Java:

interface IStack<T> extends Iterable<T> { IStack<T> Push(T value); IStack<T> Pop(); T Peek(); boolean IsEmpty(); } final class EmptyStack<T> implements IStack<T> { public boolean IsEmpty() { return true; } public IStack<T> Push(T value) { return Stack.cons(value, this); } public IStack<T> Pop() { throw new Error("Empty Stack"); } public T Peek() { throw new Error("Empty Stack"); } public java.util.Iterator<T> iterator() { return new java.util.Iterator<T>() { public boolean hasNext() { return false; } public T next() { return null; } public void remove() { } }; } } final class Stack<T> implements IStack<T> { public static <T> IStack<T> cons(T hd, IStack<T> tl) { return new Stack<T>(hd, tl); } public static <T> IStack<T> append(IStack<T> x, IStack<T> y) { return x.IsEmpty() ? y : new Stack(x.Peek(), append(x.Pop(), y)); } private final T hd; private final IStack<T> tl; private Stack(T hd, IStack<T> tl) { this.hd = hd; this.tl = tl; } public IStack<T> Push(T value) { return new <T> Stack(value, this); } public IStack<T> Pop() { return this.tl; } public T Peek() { return this.hd; } public boolean IsEmpty() { return false; } public java.util.Iterator<T> iterator() { final IStack<T> outer = this; return new java.util.Iterator<T>() { private IStack<T> current = outer; public boolean hasNext() { return !current.IsEmpty(); } public T next() { T hd = current.Peek(); current = current.Pop(); return hd; } public void remove() { } }; } } public class Main { public static void main(String[] args) { IStack<Integer> x = Stack.cons(1, Stack.cons(2, Stack.cons(3, Stack.cons(4, new EmptyStack())))); IStack<Integer> y = Stack.cons(5, Stack.cons(6, Stack.cons(7, Stack.cons(8, new EmptyStack())))); IStack<Integer> z = Stack.append(x, y); for (Integer num : z) { System.out.printf("%s ", num); } } }


Yo diría que la programación funcional es adecuada para resolver problemas, por ejemplo, problemas de IA, problemas matemáticos (esto es demasiado fácil), motor de juegos pero no demasiado adecuado para el desarrollo de GUI y controles personalizados o aplicaciones de escritorio que requieren una interfaz de usuario sofisticada. Encuentro intuitivo pensar de la siguiente manera (aunque puede estar generalizando demasiado):

Back-end Front-end Low-level C C++ High-level FP VB, C#


Yo diría que la programación funcional tendrá problemas para las cosas de bajo nivel , kernels del sistema operativo, controladores de dispositivos, etc.

Dije "tener problemas", no "no se puede usar" (debido a la equivalencia de Turing, cualquier cosa se puede usar para cualquier cosa).

Una pregunta interesante es si este problema es fundamental en la programación funcional (porque los dispositivos físicos tienen estado) o si podemos imaginar un lenguaje / entornos de programación funcional orientados a sistemas. Por ejemplo, BitC es solo parcialmente funcional (depende mucho de la mutabilidad).