2010-07-26 7 views

Respuesta

9

Podría ser útil tener en cuenta, con respecto a la notación do en sí misma, para qué es en realidad bien para. Como señala Travis Brown, anteriormente he abogado por el uso de un estilo de "aplicación de funciones" con Monad sy tipos relacionados, pero también hay otra cara: Algunas expresiones simplemente no se pueden escribir limpiamente en función directa estilo de aplicación. Por ejemplo, la siguiente puede hacer rápidamente estilo aplicativo torpe:

resultados
  • intermedio utilizado en múltiples subexpresiones, a diferentes profundidades de anidación
  • argumentos de la función más externa utilizados están anidadas en subexpresiones
  • torpe o inconsistentes orden de argumento, es decir, necesidad de aplicar parcialmente una función a algo que no sea su primer argumento
  • Control de flujo profundamente integrado basado en resultados intermedios, con subexpresiones compartidas entre ramas
  • Coincidencia de patrón o n resultados intermedios, en particular en el caso de la extracción de parte de un resultado, utilizando que para más de cálculo, a continuación, la reconstrucción de una versión modificada como el siguiente resultado

Escritura de una función tal como una sola expresión requiere generalmente o bien múltiples lambdas anidados , o el tipo de absurdo que ofusca las tonterías que dan un mal nombre al estilo sin puntos. Un bloque do, por otro lado, proporciona azúcar sintáctico para un alcance anidado fácil de resultados intermedios con flujo de control incorporado.

Lo normal sería, probablemente, extracto de este tipo subexpresiones y los pone en una cláusula where o algo, pero ya que los valores normales forman una mónada con aplicación de función como (>>=) --namely la Identity mónada - que concebiblemente podría escribir una función de este tipo de un bloque de do en su lugar, aunque la gente podría verte gracioso.


Además del material de alcance/unión, la otra cosa que un bloque de do hace por usted es elide el operador que las cadenas de subexpresiones juntos. No es demasiado difícil imaginar otros casos en los que sería bueno tener una notación para "combinar estas expresiones usando esta función dentro de este bloque", y luego dejar que el compilador complete los espacios en blanco.

En el caso fácil, donde todas las expresiones tienen el mismo tipo, ponerlas en una lista y luego plegarlas funciona bien, construyendo cadenas de esta manera usando unwords y unlines, por ejemplo. El beneficio de do es que combina expresiones con estructura común y tipos compatibles, pero no idénticos.

De hecho, el mismo principio general se puede decir de la notación "soporte de lenguaje" de la Applicative papel: ¿Dónde do bloques utilizan saltos de línea para eludir construcción monádico, soportes modismo utilizan yuxtaposición a eludir aplicación de función levantada. La notación proc para Arrow es también similar, y otros conceptos se podría expresar limpiamente de tal manera, así, por ejemplo:

  • Composición estructuras de datos, por ejemplo, la fusión de los conjuntos de resultados de algún tipo, elidiendo la función de combinación de
  • Otros lenguajes de aplicación funcionan, como el estilo "tubería hacia adelante" argumento de la primera, elidiendo el operador aplicación
  • cálculos paralelos, elidiendo la función de agregación resultado

Aunque no es demasiado difícil hacer muchos de estos ya sea en un solo tipo o en una instancia completa de Monad, sería bueno tener un trozo de azúcar sintáctico unificado y extensible para el concepto general. Ciertamente hay un hilo común atando todo esto y más, pero eso es un tema mucho más grande en realidad no relacionados con la sintaxis ...

3

Applicative tiene (mucho más limitado, y más compacto) Idiom soportes, consulte Applicative Programming with Effects, Strathclyde Haskell Medio Ambiente de la página 4. Conor McBride ha implementado estos , Creo.

No veo cómo generalizar este tipo de sintaxis especiales, pero tal vez no lo he pensado lo suficiente.

13

Mi sensación es que many Haskell programmers don't love do en absoluto, y uno de los argumentos comunes en favor del uso de Applicative cuando no se necesita toda la potencia de Monad es que los combinadores <$>, <*>, etc. permiten una muy clara y concisa estilo de codificación.

Incluso para el código monádico, muchas personas prefieren utilizar =<< explícitamente en lugar de do notación. camccann 's answer to your previous question about <*> da un argumento fantástico para esta preferencia.

Tiendo a escribir mis primeros borradores usando do y luego lo reemplazo con combinadores mientras reviso. Esto es solo una cuestión de mi propia experiencia y gusto: a menudo es más fácil para mí bosquejar las cosas de una manera más imperativa (que es más conveniente con do), pero creo que el código no do suele ser más bonito.

Para las flechas, por otro lado, no puedo imaginar no usar proc y command do. Las tuplas se vuelven tan feas tan rápido.

+0

Hombre, me siento un poco mal - usted tiene más del doble de los votos por aquí e incluso se vinculó a una de mis respuestas anteriores, pero mi respuesta fue aceptada en su lugar ... por lo que vale, de todo corazón apruebo esto ¡responder! –

7

La notación do es básicamente una forma de decir "transformar a lambdas según sea necesario y distribuir >>= entre las líneas".

Cuando es obvio qué operador se está utilizando para enrollar todo, es bueno omitir y aprovechar el operador de "nueva línea".

La nueva línea programable sería una buena manera de acercarse a la lista de makings, cadenas de aplicaciones, & c. Para hacer listas, también necesitaría un "outdent programable". En realidad, sólo podría llevar a los tres bits de significativas y hacer que todos sobrecargable:

  • Begin de do.
  • Entre do s.
  • Fin de do.

Entonces probablemente ya no deberías llamarlo do. Tal vez debería ser solo un soporte.

5

Los paréntesis idiomáticos forman una buena manera de pensar acerca de los aplicativos, pero no son la única extensión de sintaxis posible.

Philippa Cowderoy publicó una propuesta de "Applicative do" notación para el Haskell-café hace un tiempo con la observación de que cualquier función que se ve algo así como:

foo = do 
    x <- bar 
    y <- baz 
    quux y 1234 x 

donde las variables ligados por <- sólo se producen en el la última línea podría implementarse con Applicative - De hecho, implementé una macro basada en reglas de sintaxis para este esquema, que llamé 'ado'.

Esto es útil en los casos en que el orden de los efectos aplicativos difiere de la "orden natural" y asumir la existencia de 'preámbulos' en Haskell acaba desugar a:

foo = (\x y -> quux y 1234 x) <*> bar <*> baz 

Sin embargo, el ámbito léxico las reglas son un poco desconcertantes.

2

Hay una generalización de las mónadas que encaja con do notación - mónadas parametrizada. Ver Beyond Monads por sigfpe. Ejemplo de uso:

test1' = do put 1 
      x <- get 
      put (show x) 
      y <- get 
      return (x,y) 

Esta es una "mónada estado" que almacena primero un número, y luego una cadena.

3

BlazeHtml está utilizando do -notation cuando en realidad es sólo una Monoid (aunque envuelto como un Monad para poder utilizar do).

Así que una notación similar para Monoid s sería útil allí.

Si nos fijamos en el código de mi juego "Defend The King", entonces también hago un montón de mconcat ing, y como BlazeHtml, me beneficiaría de una sintaxis bonita para eso.

Cuestiones relacionadas