What is the purpose of *> and <* in Scalaase

Let's look at the implementation of the finish in the Scalaz Problem

def onFinish(f: Option[Throwable] => Task[Unit]): Task[A] =
    new Task(get flatMap {
        case -\/(e) => f(Some(e)).get *> Future.now(-\/(e))
        case r => f(None).get *> Future.now(r)
    })

      

What does *> do here?

+3


source share


1 answer


This is the syntax Apply

. I recently added a few examples of the syntax to apply subproject examples scalaz, you can see specific discussion *>

and <*

here:

https://github.com/scalaz/scalaz/blob/series/7.2.x/example/src/main/scala/scalaz/example/ApplyUsage.scala#L94-L130

The idea is that you evaluate two "efficient" computations on either side of the combinator, using an Apply instance to combine the effects, but discarding one of the resulting values. <*

throws out the value on the right and *>

throws out the value on the left.

In your example, we use Apply [Future] to combine the effects, and the effect is deferred evaluation of the future. In the first case, we get the following match:

 f(Some(e)).get *> Future.now(-\/(e))

      

So f(Some(e)).get

returns Future[Unit]

, which Task

wraps, when we apply the function f

, this task is done only for its side effects. The right half of the app Future.now(-\/(e))

is the value we want to return, in Future

, but we want this future to depend on the result of the side effect Future[Unit]

. As a result, we get a Future[-\/]

, but it won't be complete until the side effect completes.

I think parser combinators are a good example of how these combinators are easy to understand. Let's assume we have some kind of parser:

trait Parser[A]

      



This is what will consume some input and produce A in the process. Let's say we have a method that will parse a symbol:

def chr(c: Char): Parser[Char]

      

and some method that will parse an arbitrary string:

def foo: Parser[String]

      

then we can make a parser for our arbitrary string in parentheses:

val parentheticalFoo: Parser[String] = chr('(') *> foo <* chr(')')

      

this creates a parser that, although it will use an open parenthesis, then foo, then close the parentheses, it will only return the result of parsing foo. We don't care about actually receiving the output of the pairs chr('(')

and chr(')')

, but we want their input consumption effects to still be merged into the resulting parser.

+6


source







All Articles