This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Functor instance for Future to accumulate transformations | |
* to be called only when Future#get is invoked. | |
*/ | |
implicit def FutureFunctor = new Functor[Future] { | |
def fmap[A, B](r: Future[A], f: A => B) = new Future[B] { | |
def cancel(miir: Boolean) = r.cancel(miir) | |
def isCancelled() = r.isCancelled() | |
def isDone() = r.isDone() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Monad[M[_]] { | |
def unit[A](a: A): M[A] | |
def bind[A, B](ma: M[A], f: A => M[B]): M[B] | |
} | |
val ExceptionM = new Monad[({type Ex[A]=Either[Exception, A]})#Ex] { | |
def unit[A](a: A): Either[Exception, A] = Right(a) | |
def bind[A, B](ma: Either[Exception, A], f: A => Either[Exception, B]) = | |
ma match { | |
case Left(e) => Left(e) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def feab[E, A, B](fab: A => Either[E, B], fea: E => Either[E, A])(a: A): Either[E, B] = | |
fab(a) fold(fea(_) fold (Left(_), fab), Right(_)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait TransactionService { | |
def create(user: User, item: Item): Result[AlreadyPurchasedEx, Transaction] | |
} | |
trait PaymentService { | |
def buy(user: User, howMany: Int): Result[PaymentFailedEx, Int] | |
} | |
trait CreditService { | |
def expend(p: (User, Int)): Result[NotEnoughFundsEx, Int] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait TransactionService { | |
/* | |
* Create a record of user purchase. | |
* throws AlreadyPurchasedEx | |
*/ | |
def create(user: User, item: Item): Transaction | |
} | |
trait PaymentService { | |
/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BasicPurchaseService( | |
val txs: TransactionService, | |
val credits: CreditService, | |
val payments: PaymentService, | |
val log: Log | |
) extends PurchaseService { | |
def purchase(user: User, item: Item) = | |
try { | |
if(! credits.canAfford(user, item.cost)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BasicPurchaseService( | |
val txs: TransactionService, | |
val credits: CreditService, | |
val payments: PaymentService, | |
val log: PurchaseEx => Result[PurchaseEx, Receipt] | |
) extends PurchaseService { | |
val buy = credits.ensure(payments.buy)_ | |
def prchs(user: User, item: Item) = for { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sealed trait Result[+F, S] { | |
def flatMap[FF >: F, SS](f: S => Result[FF, SS]): Result[FF, SS] | |
def map[SS](f: S => SS): Result[F, SS] | |
def fold[X](ff: F => X, fs: S => X): X | |
} | |
case class Failure[+F, S](x: F) extends Result[F, S] { | |
def flatMap[FF >: F, SS](f: S => Result[FF, SS]) = Failure[FF, SS](x) | |
def map[SS](f: S => SS) = Failure[F, SS](x) | |
def fold[X](ff: F => X, fs: S => X) = ff(x) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class RichEither[L, R](val either: Either[L, R]) { | |
def map[RR](f: R => RR): Either[L, RR] = either match { | |
case Left(l) => Left(l) | |
case Right(r) => Right(f(r)) | |
} | |
def flatMap[RR](f: R => Either[L, RR]): Either[L, RR] = either match { | |
case Left(l) => Left(l) | |
case Right(r) => f(r) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class RichEither[L, R](val either: Either[L, R]) { | |
def mapRight[RR](f: R => RR): Either[L, RR] = either match { | |
case Left(l) => Left(l) | |
case Right(r) => Right(f(r)) | |
} | |
} | |
implicit def either2rich[L, R](either: Either[L, R]) = new RichEither(either) | |
/* |