18

Tony Morris gave a talk with this snippet.

He's using ReaderWriterState monad to provide controlled read/write access to an implicit context. That makes sense.

How do I use the code? I would like to see an example "main" program that uses this monad.

user1590499
  • 933
  • 3
  • 10
  • 17
Dustin Getz
  • 21,282
  • 15
  • 82
  • 131
  • 4
    There's an example linked from the comments on that gist: https://gist.github.com/2364137 – Ben James Jul 23 '12 at 19:57
  • To understand how using this Monad, translate the for (...) yield {} of the example in terms of flatMap and map and look how implicit are defined to implement Monoid Trait ( id and op method ) and Functor Trait ( fmap ) – fp4me Aug 21 '12 at 13:51

1 Answers1

19

Scalaz 7 now provides this monad, and the following is a complete working example, translated with minor revisions from the example by Michael Pilquist that's linked in the comments above.

package scalaz.example

import scalaz._, Scalaz._


object RWSExample extends App {
  case class Config(port: Int)

  def log[R, S](msg: String): ReaderWriterState[R, List[String], S, Unit] =
    ReaderWriterStateT {
      case (r, s) => (msg.format(r, s) :: Nil, (), s).point[Id]
    }

  def invokeService: ReaderWriterState[Config, List[String], Int, Int] =
    ReaderWriterStateT {
      case (cfg, invocationCount) => (
        List("Invoking service with port " + cfg.port),
        scala.util.Random.nextInt(100),
        invocationCount + 1).point[Id]
    }

  val program: RWS[Config, List[String], Int, Int] = for {
    _ <- log("Start - r: %s, s: %s")
    res <- invokeService
    _ <- log("Between - r: %s, s: %s")
    _ <- invokeService
    _ <- log("Done - r: %s, s: %s")
  } yield res

  val (logMessages, result, invocationCount) = program run (Config(443), 0)
  println("Result: " + result)
  println("Service invocations: " + invocationCount)
  println("Log: %n%s".format(logMessages.mkString("\t", "%n\t".format(), "")))
}

This is tested against Scalaz 7.2.18, which is easily available from Maven's Central Repository as a Maven or SBT dependency.

Mohan Narayanaswamy
  • 2,149
  • 6
  • 33
  • 40
Travis Brown
  • 138,631
  • 12
  • 375
  • 680
  • I am failing to see where the `Random.nextInt` fits into anything there... it doesn't come back into the `invocationCount`, so is there a reason it's not just `Unit` ? or `0` ? – Jimmy Hoffa Apr 28 '16 at 20:46
  • 1
    With Scala 7.2, the code above needs to be modified. Replace `Identity` with `Id`. This line no longer compiles: `val Need(logMessages, result, invocationCount) = program run (Config(443), 0)`, but I don't know enough Scala or Scalaz to explain why. – MrMeritology Feb 28 '17 at 06:51
  • // below line worked for me ```val (logMessages, result, invocationCount) = program run (Config(443), 0)``` – Mohan Narayanaswamy Jan 17 '18 at 09:53