2009-10-03 12 views
7

Cuando estoy aprendiendo acerca de nuevos temas de programación, suelo seguir un patrón: lo leo, lo entiendo, y luego codigo algunos ejemplos para asegurarme de que realmente lo entiendo.buscando ejercicio de aprendizaje: implementar estas mónadas

He leído mucho sobre mónadas, y confío en que las entiendo y las obtengo. Ahora estoy en una etapa en la que realmente me gustaría codificar algunas mónadas para solidificar mi comprensión, y realmente averiguar qué se necesita para implementar vincular para una variedad de tipos.

El problema es que no puedo pensar en muchas mónadas obvias para implementar, por lo que estoy buscando recomendaciones. Preferiblemente, me gustaría una lista de recomendaciones, con algunas fáciles y otras no tan fáciles.

También me doy cuenta de que, si bien las mónadas se usan para 'encapsular' efectos secundarios en programas funcionales, también son más generales que eso. Entonces, me gustaría que las recomendaciones incluyan mónadas que encapsulen los efectos secundarios y algunos generales.

Gracias!

(como nota al margen: voy a trabajar con f # para hacer esto, pero creo que esta pregunta podría aplicarse a cualquier lenguaje funcional).

Respuesta

5

Creo que el catálogo en All About Monads es un buen comienzo (la mónada continuación es realmente útil para catamorphisms, véase, por ejemplo here); adicionalmente parsers, y posiblemente transactional effects. Async es otra buena aplicación para tratar de implementar por su cuenta (lógicamente un único código de subproceso que salta a través de diferentes subprocesos reales para no bloquear).Y la mónada subyacente del Reactive Framework parece un buen desafío avanzado.

2

La lista de estructuras de datos/cálculos que siguen algún tipo de ley monádica es extremadamente rica.

Se extiende desde las listas de más datos opcionales ('a option en Fa #), continuaciones y multithreading hasta cosas muy complejas como analizadores.

Simplemente comience a implementar algunos de ellos. exercies básicos:

// Identity monad 

let something = ident { 
    let! value = id 42 
    return value 
} 

let somethingelse = ident { 
    let! value = something 
    let! otherValues = id 40 
    return value + othervalue 
} 


// Implement maybe for 'a option 
let sum = maybe { 
    let! a = maybeInputNumber("a") 
    let! b = maybeInputNumber("b") 
    let! c = maybeInputNumber("c") 
    return a + b + c 
} 

match sum with 
| None -> ... 
| Some(n) -> ... 

También podrían aumentar su comprensión por jugar un pequeño poco con funciones de ayuda y la sintaxis explícita monádico.

// Given m >>= f for m.Bind(f) 

let (>-) f monad = monad >>= (fun k -> return(f x)) 

// What's this? 
let res = ((+) 1) >- [1..10] 

Si quieres algunos ejemplos complejos, echar un vistazo a monadic parser combinators. Esto le permitirá implementar complejos programas de análisis descendente recursivo en la llanura F # (Tome un vistazo a la FParsec -Proyecto)

let parseVector = parser { 
    do! ignore $ char '(' 
    let! [x;y;z] = sepBy parseNumber "," 
    do! ignore $ char ')' 
    return new Vector(x, y, z) 
} 

Una aplicación sencilla para esto se basa en las siguientes tipos:

type 't Computation = 
    | Error of ... 
    | Result of 't 

type Input  = char list 
type 'a Parser = Input -> (('a * Input) Computation) 

Intentar aplicar unen y retorno ;-)

y como un consejo general: Si realmente quiere entender mónadas en su ambiente natural, que' Tendré que usar Haskell ;-) En F # solo hay expresiones de cálculo, solo un análogo vago, pero Haskell introduce una interfaz general para cualquier cálculo monádico. Perfecto para probarlos!

1

Aunque supongo que no es un desafío el hecho de que Haskell es el lenguaje natural para aprender acerca de las mónadas, me parece que un ejercicio muy útil es llevar los cómputos monádicos a un lenguaje que no tiene, de entrada, Haskell, como soporte super suave para ellos. Es completamente posible en cualquier idioma, y ​​en cualquier lenguaje razonablemente de alto nivel, será posible ser creativo y hacer que se vea bien, ¡aprendiendo mucho en el proceso! He visto una sintaxis monádica genial para Python (en el Valued Lessons, creo), por ejemplo.

También hay una biblioteca clojure.contrib.monads de Clojure que proporciona buenas instalaciones para usar mónadas en Lisp. Tratar de recrear algunos de ellos funcionalmente podría ser bastante instructivo. Además, utilizarlo a veces en lugar de Haskell puede ser útil para separar los patrones generales de los detalles de la sintaxis de Haskell (aunque son bastante bueno, para estar seguro).