为了使在monad上下文中可操作的任何东西,如果使用Haskell – 我只需要在给定类型的任何地方添加Monad类的实现.所以我根本没有触摸数据类型定义的源.喜欢(人为的东西)
data Z a = MyZLeft a | MyZRight a swap (MyZLeft x) = MyZRight x swap (MyZRight x) = MyZLeft x instance Monad Z where return a = MyZRight a (>>=) x f = case x of MyZLeft s -> swap (f s) MyZRight s -> swap (f s)
所以我没有触及Z的定义,而是把它当成一个monad
如何在Scala中执行此操作?似乎除了混合一些特征和定义方法map / flatMap / filter / withFilter之外,没有什么办法?
解决方法
看看
scalaz
:
// You Could use implementation in the end of this answer instead of this import import scalaz._,Scalaz._ sealed trait Z[T] case class MyZLeft[T](t: T) extends Z[T] case class MyZRight[T](t: T) extends Z[T] def swap[T](z: Z[T]) = z match { case MyZLeft(t) => MyZRight(t) case MyZRight(t) => MyZLeft(t) } implicit object ZIsMonad extends Monad[Z] { def point[A](a: => A): Z[A] = MyZRight(a) def bind[A,B](fa: Z[A])(f: A => Z[B]): Z[B] = fa match { case MyZLeft(t) => swap(f(t)) case MyZRight(t) => swap(f(t)) } }
用法:
val z = 1.point[Z] // Z[Int] = MyZRight(1) z map { _ + 2 } // Z[Int] = MyZLeft(3) z >>= { i => MyZLeft(i + "abc") } // Z[String] = MyZRight(1abc) z >>= { i => (i + "abc").point[Z] } // Z[String] = MyZLeft(1abc)
for { i <- z j <- (i + 1).point[Z] k = i + j } yield i * j * k // Z[Int] = MyZRight(6)
另见Scalaz cheatsheet和Learning scalaz.
在scalaz没有魔法 – 你可以实现这个没有scalaz.
相关:Typeclases in Scala & Haskell.
最简单的实现Monad与语法,以防您不想使用scalaz:
import scala.language.higherKinds trait Monad[M[_]] { def point[A](a: => A): M[A] def bind[A,B](fa: M[A])(f: A => M[B]): M[B] } implicit class MonadPointer[A](a: A) { def point[M[_]: Monad] = implicitly[Monad[M]].point(a) } implicit class MonadWrapper[M[_]: Monad,A](t: M[A]) { private def m = implicitly[Monad[M]] def flatMap[B](f: A => M[B]): M[B] = m.bind(t)(f) def >>=[B](f: A => M[B]): M[B] = flatMap(f) def map[B](f: A => B): M[B] = m.bind(t)(a => m.point(f(a))) def flatten[B](implicit f: A => M[B]) = m.bind(t)(f) }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。