2008-12-19 21 views
25

Acabo de terminar de leer un libro en Scala. Lo que me sorprende es que cada ejemplo en todo el libro fue numérico de una forma u otra.Casos de uso no numéricos para programación funcional?

Al igual que muchos programadores, la única matemática que uso es de matemáticas discretas y combinatorias, y generalmente eso no es matemática. Programo de manera explícita. Realmente me faltan algunos ejemplos convincentes de alternativas/suplementos funcionales a los algoritmos regulares de oo.

¿Cuáles son algunos casos de uso no numéricos para la programación funcional?

+0

¿Podría aclarar qué quiere decir con "matemático"? ¿Te refieres a "numérico"? –

+0

Gracias. Sí. Esa es la cantidad de matemáticas que he olvidado desde la universidad;) – krosenvold

+0

A cada publicación de este tipo le falta el único superconjunto de respuestas: Datos. La programación funcional está destinada a hacer el procesamiento de un conjunto de datos. La gente confunde esto con las matemáticas porque las matemáticas complejas a menudo se aplican a los conjuntos de datos. Todo el mundo menciona la concurrencia, que de nuevo es un mecanismo para procesar un conjunto de datos. La gente dice analizadores, de nuevo, procesando un conjunto de datos. El hecho de que las listas de comprensión incluso existen debería ser suficiente para señalar, estos lenguajes están completa y completamente construidos con el propósito de trabajar con conjuntos de datos. Que están creciendo en estos días, y por qué FP ahora importa. –

Respuesta

44

Mi empresa me pidió que escribiera una aplicación personalizada que permitiera a los usuarios realizar consultas ad hoc en una base de datos de archivos planos. Los usuarios de esta aplicación eran los tipos típicos de Joe Empresario. No son programadores, y es poco probable que hayan visto una declaración SQL en sus vidas.

Como resultado, tuve la tarea de desarrollar una interfaz de usuario amigable que permitiera a los usuarios seleccionar columnas, tablas, condiciones, etc. para crear una consulta. Esto es un desafío porque puedo representar la declaración de SQL en la interfaz de usuario sin crear primero una representación abstracta de la misma en la memoria.

La primera iteración fue escrita en C#. He creado una clases bote lleno para representar la sintaxis abstracta de una instrucción SQL, lo que dio lugar a un modelo de objetos muy engorroso:

  • una Participar en clase, una se une a clase de colección
  • una clase WhereClause, una clase de colección WhereClauses
  • una clase SelectedColumn, selectedColumns clase de colección
  • una clase OrderBy, OrderBy colecciones de recogida clase
  • una clase SqlStatement que agrupa todas las clases aforemtioned juntos

La conversión de una instancia de SqlStatement a una cadena fue gloriosamente dolorosa, fea y con errores. Mover la dirección opuesta, de cadena a SqlStatement, fue aún peor, ya que rompió las piezas de una cadena de SQL utilizando mucha manipulación de expresiones regulares y cadenas.

Arranqué el sistema, producí una aplicación que funcionó, pero no estaba muy contento con ella. Especialmente no sucedió cuando los requisitos comerciales de la aplicación cambiaron en mí, lo que me obligó a volver a visitar mi código C#.

Así como un experimento, Reescribí mi SqlStatement en Fa # y representado como una unión:


type dir = Asc | Desc 
type op = Eq | Gt | Gte | Lt | Lte 
type join = Inner | Left | Right 

type sqlStatement = 
    | SelectedColumns of string list 
    | Joins of (string * join) list 
    | Wheres of (string * op * string) list 
    | OrderBys of (string * dir) list 

type query = SelectedColumns * Joins * Wheres * OrderBys 

Esa pequeña cantidad de código reemplazado unos pocos cientos de líneas de C# y una docena de clases. Más importante aún, la coincidencia de patrones simplificó el proceso requerido para convertir la representación abstracta en una cadena SQL.

La parte divertida fue convertir una cadena SQL de nuevo en un objeto de consulta usando fslex/fsyacc.

Si mal no recuerdo, el código original de C# totalizó 600 líneas y alrededor de una docena de clases, muchas expresiones regulares confusas y requirió dos días para escribir y probar. En comparación, el código F # consistía en un archivo .fs de alrededor de 40 líneas, 100 líneas más o menos para implementar el analizador/analizador lexer, y consumía algunas horas de mi día para probar.

En serio, escribir esta parte de la aplicación en F # parecía una trampa, así de fácil resultó.

+2

Aunque hay muchas respuestas excelentes aquí, estoy eligiendo las tuyas porque creo que es hermosa – krosenvold

1

La coincidencia de patrones es también un lugar donde brilla la programación funcional, por lo que es muy útil en áreas como la Bioinformática.

Sin embargo, teniendo en cuenta los grandes compiladores que tenemos hoy en día, la programación funcional brilla en casi todos lados.

+0

Aunque la coincidencia de patrones se correlaciona con la programación funcional, en realidad no están directamente relacionados. En particular, muchos lenguajes funcionales tienen poco o ningún soporte para la coincidencia de patrones: Lisp, Scheme, Erlang, C# etc. –

+1

@Jon: [Erlang Pattern Matching] (http://www.erlang.org/doc/reference_manual/patterns. html "Erlang Pattern Matching") –

+0

Lo siento, debería haber sido más específico. Scheme también tiene otra forma de coincidencia de patrones. Me estaba refiriendo, como supongo que Mehrdad, a la coincidencia de patrones ML-estilo sobre los tipos de datos algebraicos. –

0

LINQ tiene una gran cantidad de señales de programación funcional. Echar un vistazo a cómo se implementa un proveedor de LINQ arbitrario podría proporcionarle algunos conocimientos prácticos.

+1

LINQ en sí mismo es funcional. Sin embargo, sus proveedores no están implementados en su mayoría en un estilo funcional. –

3

Echa un vistazo Text Processing in Python. El libro comienza con algunos ejemplos simples pero bien motivados donde las técnicas de programación funcional hacen que el código sea más fácil de leer y más probable que sea correcto.

1

Compruebe "Purely functional data structures" (y here's la tesis doctoral que inspiró el libro).

Muestran cómo se pueden crear estructuras de datos estándar en lenguajes puramente funcionales (sin efectos secundarios). Luego puede usarlos para programar cualquier cosa.

Descargo de responsabilidad: Estoy sacando un Atwood aquí, apenas he leído un par de críticas del libro y he echado un vistazo a la tesis, está en mi lista de temas pendientes.

+0

Gran libro, aunque no es fácil de leer. La tesis es bastante ilegible en mi humilde opinión. – Paul

+0

Preferí el libro también, la tesis no es tan útil. – boutta

+0

Encontré legible y académicamente fascinante pero totalmente inútil en el mundo real. –

7

La programación funcional es un paradigma similar a la programación procedural/estructurada, orientada a objetos y genérica/plantilla. Es muy completo para que puedas hacer lo que quieras.

Aparte de las matemáticas y las ciencias, facilita la combinación de analizadores sintácticos, la inteligencia artificial, la concurrencia, la evaluación dinámica, las co-rutinas, las continuas, la notación concisa (ciclo más rápido de cerebro a teclado y texto y menos código para mantener), parametización fuertemente tipada (ver tipos algebraicos de Haskell) y autorreflexión dinámica (por ejemplo, intérpretes metacirculares minimalistas con REPL).

3

"Getting Started with Erlang" tiene un amplio ejemplo de cliente/servidor (comenzando en la Sección 1.3.5) que puede adaptarse a sus necesidades.

2

Cuanto más uso un estilo funcional, mejor me gusta. Considere este fragmento de Python desde another question:

>>> testlist 
[1, 2, 3, 5, 3, 1, 2, 1, 6] 
>>> [i for i,x in enumerate(testlist) if x == 1] 
[0, 5, 7] 

Ésta es ciertamente una declaración más o menos matemática, pero hay un montón de generadores en Python. Una vez que te acostumbras, usar una lista de comprensión en lugar de un bucle es fácil de entender y menos propenso a tener un error (no obtienes errores "desactualizados").)

+0

Whoa. Parece genial;) – krosenvold

+0

¿Qué quiere decir "muchos generadores"? Son una función de idioma y puede escribir una cantidad infinita de generadores, al igual que puede generar una cantidad infinita de bucles for diferentes. –

+0

Creo que podrías hacer [línea por línea en file.readlines()] también, pero no estoy seguro y no quería probarlo, estoy ocupado esta mañana. –

2

Es cierto que muchos libros sobre programación funcional usan "programación numérica" ​​para enseñar, pero hay excepciones.

Haskell School of Expression es un libro para principiantes sobre Haskell que utiliza la multimedia como vehículo para la enseñanza.

Real World Haskell realmente no tiene ningún vehículo en particular a lo largo de todo el libro, pero hay varios capítulos que cubren la escritura de programas "reales" en un estilo funcional.

1

Reducción de la disparidad algoritmo: un programa funcional en tiempo lineal para el formato de párrafo (1997)
por Oege De Moor, Jeremy Gibbons
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.33.7923

Estructuración gráficas Paradigmas en TkGofer (1997) por Koen Claessen, Ton Vullinghs, Erik Meijer http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.5525

procesos de modelado de oficina con programas de análisis funcionales (1994) por Gert Florijn
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.1307

1

El mejor ejemplo específico que puedo dar es StringTemplate, un motor de plantillas utilizado (entre muchos otros lugares) en el generador de analizadores ANTLR.

En un artículo sobre el diseño y desarrollo de StringTemplate, Terence Parr escribió que originalmente era escéptico de la programación funcional, y se rió de sí mismo cuando se dio cuenta de que StringTemplate era esencialmente un lenguaje funcional para generar texto.

3

Tienes otro para usted:

estoy involucrado en las primeras etapas de la creación de prototipos de un conjunto de nuevos productos financieros a escala de empresa destinados a bancos de tamaño, el gobierno local, las bolsas de valores de pequeño y mediano, Probablemente estés pensando "oh, código financiero, debes estar haciendo un montón de matemáticas" - en realidad, no. Estos productos están destinados a ser altamente personalizables y permiten a los usuarios implementar reglas comerciales en puntos estratégicos de la aplicación.

Estamos usando F # para representar e interpretar las reglas comerciales. Para usar un ejemplo ingenua, permite que estamos escribiendo algo de código para el procesamiento de cheques, podemos escribir las reglas de este tipo:

type condition = 
    | Test of string 
    | And of condition * condition 
    | Or of condition * condition 
    | Not of condition 

type transactionWorkflow = 
    | Reject 
    | Approve 
    | AdministratorOverride of string 
    | If of condition * transactionWorkflow list 
     (* condition, true condition *) 
    | IfElse of condition * transactionWorkflow list * transactionWorkflow list 
     (* condition,  true condition,   false condition *) 
    | AttachForms of string list 

Usando una aplicación especial, los usuarios pueden escribir algunas reglas de negocio representados por la estructura anterior. Por ejemplo:

let checkProcessingWorkflow = 
    [If(Test("account doesn't exist") 
     ,[AdministratorOverride("Account doesn't exist. Continue?"); 
      AttachForms ["40808A - Null Account Deposit"]] 
     ); 
    If(Test("deposit > 10000") 
     ,[ 
      If(And(Test("account created within 3 months") 
        ,Test("out of country check")) 
       ,[Reject]); 
      IfElse(Test("account state = TX") 
        ,[AttachForms ["16A"; "16B"]] 
        ,[AttachForms ["1018"]] 
       ) 
     ] 
     ); 
    Approve 
    ] 

Así, en lugar de escribir un motor de reglas de negocio para gobernarlos a todos, nos ocupamos de ciertos procesos como una muy pequeña lenguaje específico del dominio intepreted por F #. Espero que este enfoque nos permita diseñar DSL legibles por negocios muy simples sin necesidad de detectar reglas conflictivas.

Por supuesto, todo lo anterior es solo código conceptual, y aún estamos en las etapas más tempranas de incluso crear prototipos de uno de nuestros sistemas de reglas. Estamos usando F # en lugar de Java o C# por una razón en particular: coincidencia de patrones.

1

para aquellos que consideran LISP un lenguaje de programación funcional, hay un servidor HTTP escrito en Common Lisp por ahí, introducido en un documento de 1994 y sigue siendo desarrollado en 2006:

para obtener más cosas modernas, es posible que desee preguntar a Google "servidor web haskell", es probable que encuentre algunos ejemplos interesantes. uno dirígeme a encontrar este sitio: http://code.haskell.org/.

2

En estos días, ni siquiera consideraría escribir un lector/analizador de DSL en un lenguaje no funcional (en sentido amplio del término). Los ADT y la coincidencia de patrones lo hacen mucho más fácil.

+0

Amen, hermano. –

1

Ted Neward escribió un artículo de 10 partes sobre Scala, dirigido a programadores de Java, y la serie terminó con la escritura de un DSL en Scala. Este DSL particular es en realidad una calculadora numérica, pero eso no es lo interesante de ella, es la forma en que el DSL se puede montar fácilmente en un lenguaje funcional

Part1

Part2

Part3

1

Realmente ¡pregunta interesante porque pensé que era el único autor que escribía libros sobre programación funcional para numéricos!

La programación funcional ha sido históricamente mucho más utilizada para la metaprogramación, es decir, programas de escritura que manipulan otros programas. Esto incluye intérpretes y compiladores (por ejemplo, para DSL), así como aplicaciones más esotéricas como demostradores de teoremas (Coq, Isabelle) y sistemas de reescritura de términos (por ejemplo, sistemas de álgebra computacional como Mathematica). La familia de idiomas Meta Language (ML) se diseñó específicamente para esto.