2011-03-25 12 views
12

En Haskell, puede utilizar el operador bind (>>=) así:Adición de enlace operador monádico de Haskell a Scala

repli :: [a] -> [a] 
repli xs = xs >>= \x -> [x,x] 

*Main> repli [1,2,3] 
[1,1,2,2,3,3] 

He leído que flatMap es el operador se unen de Scala:

def repli [A](xs: List[A]): List[A] = 
    xs.flatMap { x => List(x,x) } 

scala> repli (List(1,2,3)) 
res0: List[Int] = List(1, 1, 2, 2, 3, 3) 

Como ejercicio pedagógico, estoy tratando de agregar soporte para >>= a Scala:

class MyList[T](list: List[T]) { 
    def >>= [U](f: T => List[U]): List[U] = list.flatMap(f) 
} 
implicit def list2mylist[T](list: List[T]) = new MyList(list) 

def repliNew [A](xs: List[A]): List[A] = 
    xs >>= { x: A => List(x,x) } 

scala> repliNew (List(1,2,3)) 
res1: List[Int] = List(1, 1, 2, 2, 3, 3) 

Esto funciona perfectamente, pero solo para listas. Realmente quiero apoyar cualquier clase con un método flatMap. ¿Cuál es la mejor manera de hacerlo?

+0

(¿Algo relevante en [scalaz] (http://code.google.com/p/scalaz/)?) –

+1

Si solo está de acuerdo con los miembros de la jerarquía de colecciones, p. Ej. no 'Opción' sin trabajo adicional - entonces puede usar el método que se muestra en http://stackoverflow.com/questions/5410846 –

+1

+1 para enseñarme una nueva palabra: pedagógico – Bradford

Respuesta

16

Scalaz lo hace de la siguiente manera:

trait MA[M[_], A] { 
    def value: M[A] 
    def >>=(f: A => M[B])(implicit m: Monad[M]): M[B] = 
    m.bind(value, f) 
} 

Con las conversiones implícitas de M[A] a MA[M, A] para todos M[_] y A:

implicit def ma[M[_], A](m: => M[A]): MA[M, A] = new MA[M, A] { 
    lazy val value = m 
} 

Sólo tiene un rasgo Monad y una instancia del mismo para cada Mónada te importa:

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

¿Qué tal si agregamos un sinónimo de flatMap con una clase implícita?

implicit class BindRich[A,B](fm:{def flatMap(a:A):B}) { 
    def >>=(a:A):B = fm.flatMap(a) 
} 

Con esto en alcance cualquier objeto que tiene el método flatMap también tendrá >>=.

+1

Tenga en cuenta que esto puede usar reflejo debajo del capó. – rightfold

Cuestiones relacionadas