2011-05-13 12 views
15

Solo sé F #. No he aprendido otros lenguajes de programación funcionales. Todos los ejemplos que he visto para las mónadas solo describen los métodos de unión y unidad. F # tiene muchas palabras clave (por ejemplo, let!, do!, etc.) que le permiten hacer cosas diferentes dentro de la misma expresión computacional. Esto aparentemente le da más poder que sus métodos básicos de unión y unidad. ¿Esto es exclusivo de F # o es común en los lenguajes de programación funcionales?¿La implementación de mónadas de F # es única con respecto a la cantidad de palabras clave disponibles para ella?

Respuesta

18

Sí, creo que la sintaxis de F # para expresiones de cálculo es única, ya que proporciona soporte sintáctico directo para diferentes tipos de cálculos. Se puede usar para trabajar con monoids, mónadas y también MonadPlus cálculos de Haskell.

Escribí sobre esto en la introducción de my Master thesis. Creo que es una parte bastante legible, por lo que puede ir a la página 27 para leerla. De todos modos, voy a copiar los ejemplos aquí:

Monoid se utiliza sólo para la concatenación de valores mediante alguna operación "+" (Combine). Se puede utilizar por ejemplo para la construcción de cadenas (esto es ineficiente, pero demuestra la idea):

type StringMonoid() = 
    member x.Combine(s1, s2) = String.Concat(s1, s2) 
    member x.Zero() = "" 
    member x.Yield(s) = s 

let str = new StringMonoid() 

let hello = str { yield "Hello " 
        yield "world!" };; 

Mónadas son el ejemplo familiar que utiliza unen y retorno operaciones de expresiones comptuation. Por ejemplo tal vez mónada representa cálculos que pueden fallar en cualquier punto:

type MaybeMonad() = 
    member x.Bind(m, f) = 
    match m with Some(v) -> f v | None -> None 
    member x.Return(v) = Some(v) 

let maybe = new MaybeMonad() 

let rec productNameByID() = maybe { 
    let! id = tryReadNumber() 
    let! prod = db.TryFindProduct(id) 
    return prod.Name } 

mónadas aditivos (aka MonadPlus en Haskell) es una combinación de los dos. Es un poco como el cálculo monádico que puede producir valores múltiples. Un ejemplo común es lista (o secuencia), que puede implementar tanto bind y combinan:

type ListMonadPlus() = 
    member x.Zero() = [] 
    member x.Yield(v) = [v] 
    member x.Combine(a, b) = a @ b 
    member x.Bind(l, f) = l |> List.map f |> List.concat 

let list = new ListMonadPlus() 

let cities = list { 
    yield "York" 
    yield "Orleans" } 
let moreCities = list { 
    let! n = cities 
    yield n 
    yield "New " + n } 

// Creates: [ "York"; "New York"; "Orleans"; "New Orleans" ] 

Hay algunas palabras clave adicionales que no corresponden directamente a cualquier idea teórica. La palabra clave use se ocupa de los recursos y for y while se puede utilizar para implementar el bucle. La secuencia/lista de comprensión realmente usa for en lugar de let!, porque tiene mucho más sentido desde el punto de vista sintáctico (y for generalmente toma una secuencia, aunque puede ser, por ejemplo, asíncrona).

+0

Tomas, el enlace a su artículo anterior ya no funciona. Aquí está el nuevo enlace, http://tomasp.net/academic/theses/events/events.pdf. – kimsk

5

Las mónadas se definen en términos de operaciones bind y unit (solo). Existen otras estructuras definidas por otras operaciones (por ejemplo, en Haskell, la clase de tipo MonadPlus tiene operaciones zero y plus, que corresponden a Zero y Combine en expresiones de cálculo F #). Hasta donde yo sé, los creadores de cálculos de F # son únicos en términos de proporcionar una sintaxis agradable para la amplia gama de operaciones que admiten, pero la mayoría de las operaciones no están relacionadas con las mónadas.

2

F # binding forms que terminan en ! denot expresiones de cálculo, incluyendo let! use! do! yield! return!.

let! pat = expr in comp-expr   -- binding computation 

do! expr in comp-expr    -- sequential computation 

use! pat = expr in comp-expr   -- auto cleanup computation 

yield! expr       -- yield computation 

return! expr       -- return computation 

expresiones Computación se utilizan "para las secuencias y otras interpretaciones no estándar de la expresión de sintaxis F #". Estas formas de sintaxis ofrecen formas de sobrecargar esa sintaxis, por ejemplo, para codificar cómputos monádicos, o cálculos monoidales, y parecen ser similares a, p. la notación do de Haskell y las correspondientes formas de enlace (no mágicas) en ese idioma.

Por lo tanto, diría que admiten una sobrecarga de sintaxis para admitir otras interpretaciones de la sintaxis de expresión del idioma, y ​​esto tienen en común con muchos lenguajes, incluidos Haskell y OCaml. Sin duda es una característica de lenguaje útil y útil.


Referencias:The F# 2.0 Language Specification.

1

(Recuérdese de la memoria, que puede estar apagada.)

Aunque creo que unit y bind son la base típico de las mónadas, creo que tal vez map y join de una base diferente que he visto en trabajos académicos . Esto es un poco como funciona LINQ en C# y VB, donde la sintaxis from varia en Select o SelectMany que son similares a map y join. LINQ también tiene algunas palabras clave 'adicionales', un poco como F # aunque más ad hoc (y más adecuadas para consultar enumeraciones/bases de datos).

No conozco otros lenguajes funcionales como F # que efectivamente "elevan" la mayor parte del flujo de control y otras sintaxis a mónadas (bueno, "expresiones de cálculo", que pueden ser o no mónadas).

+1

Por lo que vale, la base "canónica" sería los tres de mapa, unidad y unión; todos son distintos y ortogonales y el resultado es matemáticamente agradable. La operación "vincular" es un mapa compuesto + combinación que solo existe porque es conceptualmente más conveniente para la programación con mónadas; en el caso de LINQ, imagine hacer todo con solo 'Seleccionar' y' Concat' en lugar de 'SeleccionarMany'. –

Cuestiones relacionadas