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.

Peter Becich (2) [Avatar] Offline
#1
Hello,

I'm confused by the "Next" type in chapter 8. How might I add some type bounds for clarification?

In frdomain.ch8.cqrs.service.AccountService:

  private implicit def liftEvent[Next <: Account](event: Event[Next]): Command[Next] = liftF(event) 
compiles.

However, none of these type bounds compile in frdomain.ch8.cqrs.lib. Just three guesses:

 trait Event[+Next <: Free[Event, Aggregate]] {
  def at: DateTime
}

frdomain.ch8.cqrs.lib.Event's type parameters do not match type S's expected parameters:
type Next's bounds <: scalaz.Free[frdomain.ch8.cqrs.lib.Event,frdomain.ch8.cqrs.lib.Aggregate] are stricter than type _'s declared bounds >: Nothing <: Any
trait Event[+Next <: Free[Event, Aggregate]] {
                                 ^


where type "S" presumably refers to "S" in "class Free[S[_], A]".
From
  type Command[A] = Free[Event, A] 

, S =:= Event.

 trait Event[+Next <: Aggregate] {
  def at: DateTime
}


trait Event[+Next <: Event[_]] {
  def at: DateTime
}



Am I going about this in completely the wrong way? It's a terrific book. Thank you
Debasish Ghosh (116) [Avatar] Offline
#2
May be I am missing something. When do u get the compilation error ? When I try the following, it gives green .. Currently all is in 1 project - I have plans of refactoring though ..


Apples-MacBook-Pro:frdomain debasishg$ sbt
[info] Loading global plugins from /Users/debasishg/.sbt/0.13/plugins
[info] Loading project definition from /Users/debasishg/projects/frdomain/project
[info] Set current project to FRDomain (in build file:/Users/debasishg/projects/frdomain/)
> clean
[success] Total time: 2 s, completed 7 Feb, 2016 12:11:49 AM
> compile
[info] Updating {file:/Users/debasishg/projects/frdomain/}FRDomain...
[info] Resolving jline#jline;2.12.1 ...
[info] Done updating.
[info] Compiling 112 Scala sources to /Users/debasishg/projects/frdomain/target/scala-2.11/classes...
[success] Total time: 51 s, completed 7 Feb, 2016 12:12:43 AM


Thanks.
Peter Becich (2) [Avatar] Offline
#3
Hello, thanks for your response.

The code from your repository definitely compiles. I am just confused by the "Next" parameter. When I try to add some type bounds, I think it breaks compilation.
Debasish Ghosh (116) [Avatar] Offline
#4
The key thing to note is that in the definition of Free in scalaz we have

abstract class Free[S[_], A] { //..


This means S is the existential parameter and the compiler automatically puts a bound <: Any >: Nothing. An existential type means that the exact type is not known - it can be anything and code that depends on existentials also cannot assume any restriction there. Have a look here (http://www.artima.com/pins1ed/combining-scala-and-java.html#29.3).

I guess you cannot restrict it here ..

Thanks.
arya (7) [Avatar] Offline
#5
Hi Debasish, I am excited about the book (and am recommending it to others) but I just reached Chapter 8 myself and I noticed the implementation in Section 8.4 (specifically the chaining with Next) is kind of messed up (no offense!). Notice how the `next` members feel like they are only there to conform to the template? (and why doesn't Opened need to take a Next as input when all the others do?) They aren't needed after all. smilie

So first, the S[_] in Free[S[_], A] is not an existential type, but a higher-kinded type, another case of Scala using _ to mean too many different things in different contexts:
e.g.:
val foo: S[_] = ??? // existential type
class Foo[S[_]] { /* */ } // higher-kinded type


But back to Free interpreters. In:

case class AccountNo(string: String) extends AnyVal

sealed trait Event[A] // #1
case class Opened(no: AccountNo, name: String, openingDate: Option[Date]) extends Event[AccountNo] // #2
case class Closed(no: AccountNo, closeDate: Option[Date]) extends Event[Unit]
case class Debited(no: AccountNo, amount: Amount) extends Event[Unit]
case class Credited(no: AccountNo, amount: Amount) extends Event[Unit] // #3

  val composite =
    for {
      n <- open("a-123", "debasish ghosh", Some(today)) // #4
      _ <- credit(n, 10000) // #5
      _ <- credit(n, 30000)
      _ <- debit(n, 23000)
    } yield (())


#1 an Event[A] represents a command that will return an A
#2 Opened will return an AccountNo, so it extends Event[AccountNo]
#3 Credited will return Unit, so it extends Event[Unit]
#4 calling open(...) produces an AccountNo, which we bind to n
#5 calling credit(...) produces unit, which we discard by binding to _

We can utilize the "free functor" instead of defining our own Functor (and introducing `next` just to give us something to map over) by using Free.liftFC instead of Free.liftF (even in scalaz 7.1) and then we can use Free.runFC to interpret the program according to a NaturalTransformation from Command to State.

I uploaded a complete example at https://github.com/debasishg/frdomain/pull/28

Let me know if you want to chat more, and keep up the good work!


arya (7) [Avatar] Offline
#6
P.S. Side benefit of not having an onInit function in Opened is that now all of the Event classes can be persisted directly!
Debasish Ghosh (116) [Avatar] Offline
#7
Thanks for the PR. I was planning to add the Natural Transformation and CoYoneda bit in the next round of changes. Initially I was not sure if I should speak about NT or CY - You made my life easier.

Thanks.
bhericher (34) [Avatar] Offline
#8
Do you plan to show the use of a library like Freek or eff-cats?

Thank you

Benoit
Debasish Ghosh (116) [Avatar] Offline
#9
I am planning to have some examples as part of the online repository, NOT as part of the core book. Let's see.