The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

Phil Derome (48) [Avatar] Offline
#1
Section 8.4.3 Interpreters - hideouts...

see next comment (I cannot delete this, sorry)
Phil Derome (48) [Avatar] Offline
#2
Section 8.4.3 Interpreters - hideouts...

Both in code and in book's Listing 8.6, the handleCommand match case for Opened makes no call to updateState, but I think it should. Listing 8.3 for updateState has a provision for the Opened event so it seems like the call should be made. When thinking of the domain, and staying away from code, we would think that opening an account should generate an entry into our state map of accounts. I reproduced shell session Run Sample Session (listing 8.7) and confirms Opened event was missing.

handleCommand is parameterized by A, which seems to aim at being generic but I fail to see the benefit given that we use concrete type Account all over the place (the validate methods return types, or also open, close, debit, credit methods in the trait). Would not it make sense to embrace that Commands is coupled with Accounts and could be really viewed as AccountCommands (which I will concede is more verbose)? I am raising this question more to understand how Free-Monads are used in the FP field and when parameterization is desired.

It would seem that handleCommand in object Commands would read more easily if it were called interpret since it takes an event type as input and not a command (and similarly some parameter action could be renamed event in RepositoryBackedInterpreter.apply).

Listing 8.7 has a few errors when trying to use as is in a shell. res0.unsafePerformAsync requires application ((_)). For res2, we credit first account without opening (you get a runtime exception when crediting an unopened account by author's design). The expected Opened events we see in Listing 8.7 indeed don't show up as a result of the missing updateState I mentioned first.

Still, it does not really deter from the message you're conveying and appreciate this chapter a lot.
Debasish Ghosh (116) [Avatar] Offline
#3
Thanks for your comments .. Here are my observations ..

1. Regarding Listing 8.6, I am not sure why updateState should be called as there is no current state. The account is being opened as a new one.

2. Regarding handleCommand being generic, the A in handleCommand has nothing to do with Account. It's the parameter that's generic to Task or Event. Note the function handleCommand is part of RepositoryBackedAccountInterpreter which is an abstraction coupled to Account. Hence I don't see any correlation between Account being used in the function and making the function generic.

3. You are correct regarding unsafePerformAsync. I missed the argument. I will update the code base and report this to the publisher to add to the errata list. You just need to do the following change ..

scala> import scalaz._
scala> import Scalaz._
scala> import \/._
scala> res0.unsafePerformAsync {
     |   case -\/(ex) => ex.printStackTrace
     |   case \/-(value) => println(value)
     | }


And the entire session runs ok. Please have a look at the gist https://gist.github.com/debasishg/33d5a9f0d497abd280a6af2dbb60fbbd for a session I ran just now with the above change.

Let me know if you have any more question.

Thanks.
Phil Derome (48) [Avatar] Offline
#4
Your clarification on #1 helps. I was looking for when lines 24-25 of AccountService.scala (updateState method) gets called for case Opened. That turns out to be snapshot method, which makes sense. And you are right there's no need to have updateState do that within the context of handleCommand. I must have been confused about the responsibilities of snapshot and handleCommand somehow.

Your clarification of #2 helps as well, thanks. I now need to review this example, chapter, and code in more detail and understand more precisely the mechanics of Free: RepositoryBackedAccountInterpreter.handleCommand must be a full function (not partial), hence the pattern match must be completely exhaustive, and yet I don't see why. All I see is a generic pattern match on Event[A] that is exhaustive on 4 concrete types (Opened, Credited, Debited, Closed, and btw my Intellij sees red in that method but I digress). Not sure if you explain in the book but I'd like to understand why the pattern match is safe and exhaustive as FP experts are known to shy away from partial functions.

Your clarification on #3 also works and I reproduced the gist in REPL and got the expected results.