Lazily composing M[Boolean] using ||, && etc

20 views
Skip to first unread message

Chris Marshall

unread,
May 4, 2017, 9:14:21 AM5/4/17
to sca...@googlegroups.com
in the following:

    def expr1: Boolean = ???
    def expr2: Boolean = ???

    val res: Boolean = expr1 || expr2

Then is expr1 is true will not be evaluated. Is there a mechanism `foo` such that the following (assuming M is a monad) ...

    def expr1: M[Boolean] = ???
    def expr2: M[Boolean] = ??? 

    val res: M[Boolean] = foo(expr1, expr2)

...will behave similarly ~> that is, expr2 would not be evaluated *at all* if expr1 is true. This works:

    def foo[M: Monad](expr1: M[Boolean], expr2: M[Boolean]): M[Boolean] = expr1.ifM(ifTrue = M.pure(true), ifFalse = expr2)

But it feels rather clumsy. Is there a better way?

Chris

oxbow_lakes

unread,
May 5, 2017, 6:59:30 AM5/5/17
to scalaz
Is there any appetite for this?

trait ToBooleanMOps {
implicit def ToBooleanMOps[M[_]](m: M[Boolean]): BooleanMOps[M] = new BooleanMOps[M](m)
}

private object BooleanM {
def True[M[_]: Monad]: M[Boolean] = Monad[M].pure(true)
def False[M[_]: Monad]: M[Boolean] = Monad[M].pure(false)
def Negate[M[_]: Functor](m: M[Boolean]): M[Boolean] = Functor[M].map(m)(!_)
}

final class BooleanMOps[M[_]](val self: M[Boolean]) extends AnyVal with Ops[M[Boolean]] {
import BooleanM._
def negateM (implicit M: Functor[M]): M[Boolean] = Negate(self)
def orM (that: => M[Boolean])(implicit M: Monad[M]): M[Boolean] = M.ifM(self, True, that)
def andM (that: => M[Boolean])(implicit M: Monad[M]): M[Boolean] = M.ifM(self, that, False)
def impliesM(that: => M[Boolean])(implicit M: Monad[M]): M[Boolean] = M.ifM(self, that, True)
def iffM (that: M[Boolean])(implicit M: Monad[M]): M[Boolean] = M.ifM(self, that, Negate(that))
def xorM (that: M[Boolean])(implicit M: Monad[M]): M[Boolean] = M.ifM(self, Negate(that), that)

def norM (that: => M[Boolean])(implicit M: Monad[M]): M[Boolean] = Negate(orM(that))
def nandM (that: => M[Boolean])(implicit M: Monad[M]): M[Boolean] = Negate(andM(that))

def ifTrueM [A](that: => M[A])(implicit M: Monad[M]): M[Unit] = whenM_(that)
def ifFalseM [A](that: => M[A])(implicit M: Monad[M]): M[Unit] = unlessM_(that)
def whenM_ [A](that: => M[A])(implicit M: Monad[M]): M[Unit] = M.bind(self)(b => M.whenM (b)(that))
def unlessM_ [A](that: => M[A])(implicit M: Monad[M]): M[Unit] = M.bind(self)(b => M.unlessM(b)(that))
}
Reply all
Reply to author
Forward
0 new messages