Skip to content

Instantly share code, notes, and snippets.

@ubourdon
Last active August 29, 2015 14:27
Show Gist options
  • Save ubourdon/0b17f0b43a68c89b74e1 to your computer and use it in GitHub Desktop.
Save ubourdon/0b17f0b43a68c89b74e1 to your computer and use it in GitHub Desktop.
Why have this compilation error & how to fix it
/** In fact I try to write parametric Eventsourcing apply function
* And which allow me to have a parametric function for CommandHandler[D] too.
*/
trait ApplyTo {
def applyTo[E, S](startingState: S)(events: List[E])(implicit de: DomainEvent.Aux[E, S]): S = {
events.foldLeft(startingState) { (currentState, event) => de.apply(currentState, event) }
}
}
@implicitNotFound("No member of type class DomainEvent found for type ${A}")
trait DomainEvent[A] {
type State
def apply(currentState: State, event: A): State
}
object DomainEvent {
//def apply[T: DomainEvent]: DomainEvent[T] = implicitly[DomainEvent[T]]
type Aux[A, S] = DomainEvent[A] { type State = S }
implicit object TicketEventTypeclass extends DomainEvent[TicketEvent] {
type State = TicketModel.State
override def apply(currentState: State, event: TicketEvent): State = ticket.models.apply(currentState, event)
}
}
trait TicketCommandHandler extends ApplyTo {
type DomainEither[DomainError, State] = EitherT[Future, DomainError, State]
type NextState = TicketModel.Ticket
type TicketEither[A] = DomainEither[TicketError, A] // <: TicketModel.State
def CommandHandler(command: TicketCommand)(implicit eventReader: EventStream.Id => Future[List[TicketEvent]] = Eventstore.read[TicketEvent],
eventWriter: (EventStream.Id, List[TicketEvent]) => Future[WriteEventsCompleted] = Eventstore.write[TicketEvent]): TicketEither[TicketModel.State] = {
val streamId = ticketEventStreamId(command)
eventReader(streamId).map { events => applyTo(TicketModel.EmptyTicket: TicketModel.State)(events) }
.map { state => (state, decide(state, command)) }
.flatMap { case (state, decideResult) =>
decideResult.traverse { events =>
eventWriter(streamId, events).map { _ => applyTo(state)(events) }
}
} |> fEitherT
}
private def ticketEventStreamId(command: TicketCommand): EventStream.Id = EventStream.Id(s"ticket-${command.aggregateUid.safeValue}")
}
object TicketCommandHandler extends TicketCommandHandler
object TicketModel {
sealed trait State
case object EmptyTicket extends State
case class Ticket(uid: SafeTicketUid,
agencyUid: SafeAgencyUid,
user: TicketUser,
operatorUid: SafeOperatorUid,
infos: TicketInfos,
openedDate: DateTime,
journal: List[OtherTicketEvent],
isClosed: Boolean = false) extends State
}
trait GenericTrait {
def generic[A: TypeClass](x: TypeClass[A]#Result)(y: List[A]): TypeClass[A]#Result =
y.foldLeft(x) { (a, b) => TypeClass[A].aMethod(a, b) }
}
import scala.annotation.implicitNotFound
@implicitNotFound("No member of type class TypeClass found for type ${A}")
trait TypeClass[A] {
type Result
def aMethod(x: Result, y: A): Result
}
object TypeClass {
def apply[T: TypeClass]: TypeClass[T] = implicitly[TypeClass[T]]
implicit object InstanceTypeclass extends TypeClass[AnInstance] {
type Result = AResult
override def aMethod(x: Result, y: AnInstance): Result = ???
}
}
case class AnInstance()
case class AResult()
/**
* [error] /../TypeClass.scala:3: type mismatch;
[error] found : a.type (with underlying type domain.service.TypeClass[A]#Result)
[error] required: _5.Result where val _5: domain.service.TypeClass[A]
[error] y.foldLeft(x) { (a, b) => TypeClass[A].aMethod(a, b) }
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
* /
@mandubian
Copy link

I have to leave, i'll answer later...
that's the last part of the question... your code compiles but how do you use it... your type-dependent is a bit weird and you need to show some usage code to see what is the right way to write it ;)

@ubourdon
Copy link
Author

No it's ok this compile. But I lost some message i post in gist.
Thx for your help.

@ahoy-jon
Copy link

Should events: List[E] be an HList instead ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment