查了一下MonadPlus typeclass可以提供这个函数。那么我们就沿着惯用的套路获取一下KeyLog的MonadPlus实例。 MonadPlus trait的定义如下:scalaz/MonadPlus.scala 1 trait MonadPlus[F[_]] extends Monad[F] with ApplicativePlus Plus又定义了抽象成员plus[A],那么获取MonadPlus实例必须实现empty[A]: F[A]和plus[A](a: F[A], b: F[A]): F[A]。 我们知道Monad实例类型必须是高阶的M[_],那么如果Monad实例同时又具备Monoid特性的话,那么就可以使用MonadPlus来描述它的性质。 我们用MonadPlus提供的操作符号<+>来示范: 1 List(1,2,3) <+> List(4,5,6) //> res4: List[Int] =
函数集合及定义在其上的>=>运算构成幺半群,幺元是return P.S.用>=>描述的Monad laws,更大的意义在于这3条是形成数学范畴所必须的规律,从此具有范畴的数学意义,具体见Category theory MonadPlus 同时满足Monad和Monoid的东西有专用的名字,叫MonadPlus: class (Alternative m, Monad m) => MonadPlus m where mzero :: >>=也能搞定: > [1..50] >>= \x -> if ('7' `elem` show x) then [x] else [] [7,17,27,37,47] 条件表达式看起来有些臃肿,有了MonadPlus
//> res4: scalaz.Id.Id[(List[Int], Unit)] = (List(1, 2, 3),()) 因为StateT实现了MonadPlus private trait StateTMonadStateMonadPlus[S, F[_]] extends StateTMonadState[S, F] with StateTHoist[S] with MonadPlus [({type λ[α] = StateT[F, S, α]})#λ] { implicit def F: MonadPlus[F] def empty[A]: StateT[F, S, A] b: => StateT[F, S, A]): StateT[F, S, A] = StateT(s => F.plus(a.run(s), b.run(s))) } 当然,这个StateT的F必须是MonadPlus
implicit G: MonadTrans[G]): G[F, A] = G.liftM(self) 5 6 def whileM[G[_]](p: F[Boolean])(implicit G: MonadPlus : F[Boolean]): F[Unit] = F.whileM_(p, self) 9 10 def untilM[G[_]](p: => F[Boolean])(implicit G: MonadPlus
要看看 filtering 要如何转换成用 list monad 来表达,我们可以考虑使用 guard 函数,还有 MonadPlus 这个 type class。 MonadPlus 这个 type class 是用来针对可以同时表现成 monoid 的 monad。 下面是他的定义: class Monad m => MonadPlus m where mzero :: m a mplus :: m a -> m a -> m a mzero 因为 list 同时是 monoid 跟 monad,他们可以是 MonadPlus 的 instance。 guard 这个函数被定义成下列形式: guard :: (MonadPlus m) => Bool -> m () guard True = return () guard False = mzero
trait ListInstances extends ListInstances0 { 2 implicit val listInstance = new Traverse[List] with MonadPlus