Domanda

I'm studying Michael Pilquist's excellent state monad lecture here. I get stuck at 54 min with two questions.

  1. If ofs is an Option[FollowerStats], what is the ? operator? I can't find a ternary operator on Option in Scala 2.10.2

  2. How does the last generator put an updated cache (with hit or miss incremented) back into the State result of the checkCache method? The returned State seems to be be discarded and the for comprehension seems to only yielding the Option[FollowerStats]

.

def checkCache(u: String): State[Cache, Option[FollowerState]] = for {
    c <- State.get[Cache]
    ofs <- State.state {
        c.get(u).collect {
            case Timestamped(fs, ts) if !state(ts) => fs
        }
    }
    _ <- State.put(ofs ? c.recordHit | c.recordMiss)
} yield ofs

To try and understand I attempted to re-write the for comprehension, but it's not helped.

State.get[Cache].flatMap{ c => 
    State.state{c.get(u).collect(...)}.flatMap{ ofs =>
        State.put(ofs ? c.recordHit | c.recordMiss).map{ _ =>
            ofs
        }
    }
}

Update: I think I've grasped the key to point 2 thanks to the answers. I didn't realise that that the yield is essentially saying: take the last state s => (s,()) from the put and replace the Unit value type with ofs, to get s =>(s,ofs). I guess the key is realising that the yield isn't literally returning ofs, but it's translated as State.map.

Update Understand the option bit now. I guess the presentation still uses the implicits from Scalaz although it's deriving the state monad.

È stato utile?

Soluzione

First for the ternary operator.

ofs ? c.recordHit | c.recordMiss

Is to equivalent to:

if (ofs.isDefined) c.recordHit else c.recordMiss

Or:

ofs.fold(c.recordMiss)(_ => c.recordHit)

It's provided by Scalaz and implemented as an implicit class (OptionOps) that provides a ? method for Option that returns a Conditional class that has a | method. This is a case where I'm not sure the extra concision is worth the confusion, but people use it, so it's worth knowing about.

For the state update, consider the following simplified example:

val inc: State[Int, Unit] = for { i <- get[Int]; _ <- put(i + 1) } yield ()

It might look at first like we're "discarding" the state and only yielding unit, but the value of inc is actually the entire state-manipulating computation (in this case one that doesn't return any relevant or interesting value), including the update.

Altri suggerimenti

  1. The ?| operator comes from the boolean syntax of scalaz. Have a look here at BooleanOps. It's actually 2 functions, first ? and then | on the Conditional.

  2. The updated cache is actually the result of running the State action. If you look earlier in the video, State should have been defined as something that, given a state action and an initial state s, running the state action with s results in a (a, s2) which is a pair of: (a) the value computed (represented as a in the tuple) from the passed in state and (b) the new state after the action has been executed (represented as s2).

Just note that the new Cache is not actually computed until the initial Cache is run though the monadic action.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top