2011-03-25 50 views
12

在Haskell中,你可以使用綁定運營商(>>=)是這樣的:添加Haskell的單子綁定運營商Scala的

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

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

我讀過flatMap是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) 

作爲一個教學練習,我試圖在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) 

這很好,但只適用於列表。我真的想要用flatMap方法來支持任何類。這是什麼最好的方式呢?

+0

(在[scalaz]任何有關(http://code.google.com/p/scalaz/)?) – 2011-03-25 17:52:41

+1

如果你是好與合集層次的唯一成員 - e.g。不'Option'沒有額外的工作 - 那麼你可以使用http://stackoverflow.com/questions/5410846 – 2011-03-25 18:14:51

+1

+1教我一個新詞中所示的方法:教學 – Bradford 2011-03-25 22:54:01

回答

16

Scalaz做它,如下所示:

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

M[A]隱式轉換爲MA[M, A]所有M[_]A

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

你只需要一個特徵Monad併爲每一個它的實例單子你關心:

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

怎麼樣增加對flatMap的代名詞和一個隱含的類?

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

有了這個範圍具有方法flatMap任何對象也將有>>=

+1

注意,這可以使用反射罩下。 – rightfold 2014-07-15 08:43:06