Skip to content

Instantly share code, notes, and snippets.

View justinhj's full-sized avatar

Justin Heyes-Jones justinhj

View GitHub Profile
@justinhj
justinhj / purefp1.scala
Created March 12, 2020 18:29
A pure function
def functionExample(a: A): B = {
// ... do something with A
// .. return a value of type B
}
@justinhj
justinhj / MyThrowable.scala
Last active February 25, 2020 02:36
I called this Throwable but it's actually just an implementation of Try (and Functor/Monad instance of it)
object MyThrowable {
// This is just here to keep Wartremover happy
@SuppressWarnings(Array("org.wartremover.warts.Equals"))
implicit final class AnyOps[A](self: A) {
def ===(other: A): Boolean = self == other
}
// Define Try and make it a monad/functor
sealed trait Try[+T]
package org.justinhj
import zio.blocking.Blocking
import zio.clock.Clock
import zio.console._
import zio.random.Random
import zio.system.System
import zio.internal.PlatformLive
import zio.DefaultRuntime
import zio._
val finalState2 = finalEvents.map(eventToState).combineAll
println(show"Final state 2:\n$finalState2")
/* Output:
Final state 2:
Account holder: Ben Johnson
Balance: 80
*/
val (finalEntity, finalEvents) =
commands.foldLeft((sampleAccount, List.empty[BankAccountEvent])) {
case ((acc, events), cmd) =>
val newEvents = acc.processCommand(cmd)
val newAcc = newEvents.foldLeft(acc) {
case (acc, evt) =>
acc.processEvent(evt)
}
(newAcc, events ++ newEvents)
}
val t1 = Instant.now
val sampleAccount = AccountEntity(1, AccountState(0, None))
val commands = List(
DepositCmd(t1.plusSeconds(10), 100),
PurchaseCmd(t1.plusSeconds(20), 120),
AssignAccountHolderCmd(t1.plusSeconds(40), "Bob Johnson"),
DepositCmd(t1.plusSeconds(40), 100),
AssignAccountHolderCmd(t1.plusSeconds(50), "Ben Johnson"),
case class AccountEntity(id: Int, state: AccountState)
extends PersistentEntity[Int, AccountEntity] {
override type Command = BankAccountCommand
override type Event = BankAccountEvent
override type State = AccountState
// Applies the command to the current state, returning a list of events
def processCommand(command: Command) : List[Event] = {
command match {
def eventToState(event: BankAccountEvent): AccountState = {
event match {
case DepositEvt(time, amount) =>
AccountState(amount, None)
case PurchaseEvt(time, amount) =>
AccountState(-amount, None)
case AssignAccountHolderEvt(time, accountHolder) =>
AccountState(0, accountHolder.some)
}
}
// When the left and right hand side are set we take the right side
(LastOption("Nero".some) |+| LastOption("Titus".some)).show
// res1: String = "Titus"
// When the left is None and the right hand side is set we also take the right side
(LastOption(None: Option[String]) |+| LastOption("Titus".some)).show
// res2: String = "Titus"
// When the left side is set and the right side is None we keep the left side
(LastOption("Nero".some) |+| LastOption(None: Option[String])).show
AccountState(100, "Nero".some) |+| AccountState(120, "Titus".some)
// res1: AccountState = AccountState(220, Some("NeroTitus"))