2010-01-02 33 views
23

(¿Cómo) es posible representar mónadas en Scala de una manera genérica (como la clase de tipo Monad en Haskell)? ¿Es de alguna manera posible definir un trait Monad para este propósito?rasgo Monad en Scala

Respuesta

40

usted podría intentar algo como esto:

trait Monad[+M[_]] { 
    def unit[A](a: A): M[A] 
    def bind[A, B](m: M[A])(f: A => M[B]): M[B] 
} 

// probably only works in Scala 2.8 
implicit def monadicSyntax[M[_], A](m: M[A])(implicit tc: Monad[M]) = new { 
    private val bind = tc.bind(m) _ 

    def map[B](f: A => B) = bind(f compose tc.unit) 

    def flatMap[B](f: A => M[B]) = bind(f) 
} 

implicit object MonadicOption extends Monad[Option] { 
    def unit[A](a: A) = Some(a) 

    def bind[A, B](opt: Option[A])(f: A => Option[B]) = opt flatMap f 
} 

Usted, por supuesto definir objetos implícitos similares para cualquier otra mónada que su corazón desea. En términos de Haskell, puede pensar en Monad como tipo de clase y MonadicOption como una instancia particular de esa clase de tipo. La conversión implícita monadicSyntax simplemente demuestra cómo se podría usar esta clase de tipos para permitir el uso de las for de Scala -comprehensiones con cualquier cosa que satisfaga la clase de tipo Monad.

En general, la mayoría de las cosas en la biblioteca estándar de Scala que implementan flatMap son mónadas. Scala no define una clase de tipo genérica Monad (aunque eso sería muy útil). En cambio, se basa en un truco sintáctico del analizador para permitir el uso de for -comprehensions con cualquier cosa que implemente los métodos apropiados. Específicamente, esos métodos son map, flatMap y filter (o foreach y filter para la forma imperativa).

+0

Gracias, esto era exactamente lo que estaba buscando. Solo quería definir funciones genéricas de mónada y transformadores de forma general ... – Dario

+3

En realidad, no va a usar esto para nada real, ¿verdad? :-) En serio, he estado trabajando con Scala por un tiempo, y he descubierto que muchos casos en los que Haskell usaría la clase de Monad simplemente no aparecen en Scala debido a los rasgos y la subtipificación. La clase de tipos dada arriba, aunque es genial, ciertamente no sería la manera idiomática de resolver problemas en Scala. –

+1

Pero aparecen. Aparecen todo el tiempo. Un par de veces al día, quiero 'liftA2' o' sequenceA'. De acuerdo, estos solo requieren de Applicative en lugar de Monad, pero aún así, si estos no aparecen en su programación, entonces debe escribir algo muy simple. – Apocalisp

14

Puede encontrar el proyecto scalaz interesante; tiene muchas otras cosas (funcionales) además de una implementación de mónadas.

2

Scala logra una potencia similar a las clases de tipos de Haskell a través del uso de parámetros implícitos, particularmente límites de vista y límites de contexto. Puede ver tales cosas en uso particularmente en Scala 2.8, con características como Ordering y Numeric.

Dicho esto, mire el proyecto Scalaz. Tiene mónadas, funcionadores, flechas ... todo el shebang.

4

http://www.codecommit.com/blog/ruby/monads-are-not-metaphors

Aquí está un artículo útil y bastante largo sobre el patrón Mónada y su aplicación en la Scala de Daniel, que escribió el aceptada respuesta para esta pregunta

(Para los que se tropiezan con esta pregunta "antigua" a través de las formas místicas de sitio de búsqueda de StackOverflow.)

Cuestiones relacionadas