package com.github.everpeace
object BiKleisliSample {
def main(args:Array[String]): Unit = {
import scalaz.Scalaz._
import scalaz.Monad._
import scalaz.Comonad._
import com.github.everpeace.BiKleislis._
import com.github.everpeace.DistributiveLaws._
case class User(name: String)
case class Person(name: String)
case class AccessRejectedError(message:String)
object PersonRepository {
def search(s: String): Person = Person(s)
def update(p: Person, s: String): Person = Person(s)
}
type AccessTokenComonad[X] = (User, X)
type AuthorizationErrorMonad[X] = Either[AccessRejectedError, X]
val search = (s: String) => PersonRepository.search(s)
val updateMrY = (p: Person) => PersonRepository.update(p, "Mr.Y")
val authMap: Map[ScalaObject, Map[User, Boolean]]
= Map(search -> Map(User("bob") -> true,
User("alice") -> true),
updateMrY -> Map(User("bob") -> true))
def authorize[X, Y](f: X => Y): AccessTokenComonad[X] => Boolean = {
case (u, x) => authMap.getOrElse(f, Map.empty).getOrElse(u, false)
}
def withAccessCheck[X, Y](f: X => Y): AccessTokenComonad[X] => AuthorizationErrorMonad[Y] = {
case (u, x) => if (authorize(f)(u, x)) {
Right(f(x))
} else {
Left(AccessRejectedError(u.name + " is not granted."))
}
}
val searchAndUpdateToMrY = ★☆(withAccessCheck(search)) >>> ★☆(withAccessCheck(updateMrY))
println(searchAndUpdateToMrY(User("alice"), "alice"))
println(searchAndUpdateToMrY(User("bob"), "bob"))
val sample_arrow = ★☆(withAccessCheck(search)) &&& searchAndUpdateToMrY
println(sample_arrow(User("bob"),"bob"))
println(sample_arrow(User("alice"),"bob"))
}
}