Created
September 19, 2014 14:10
-
-
Save xuwei-k/756ae67f1f5563fbf265 to your computer and use it in GitHub Desktop.
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
libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.1.0" | |
//libraryDependencies += "org.typelevel" %% "scalaz-contrib-210" % "0.1.5" // for scalaz 7.0.x | |
scalaVersion := "2.10.4" |
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
package either_and_future_sample | |
import scalaz._ | |
import scala.concurrent.{ExecutionContext, Future} | |
import scalaz.std.scalaFuture._ // for scalaz 7.1.0 | |
// import scalaz.contrib.std.scalaFuture._ // for scalaz 7.0.x | |
import either_and_future_sample.Main.{UserId, context} | |
sealed trait Error | |
/** 引数であたえられたUserIdのUserが、そもそも存在しなかった場合 */ | |
final case class UserNotFound(userId: UserId) extends Error | |
/** データベースにつながらなかったとか、そういうの */ | |
final case class ConnectionError(message: String) extends Error | |
final case class User(id: UserId, name: String) | |
object UsersRepository { | |
def followers(userId: UserId): Future[Either[Error, List[User]]] = { | |
// 失敗した場合に、次のものが呼ばれるかどうか?をわかりやすくするために、printして、かつ失敗を固定で返す | |
println("call followers " + userId) | |
Future.successful(Left(UserNotFound(userId))) | |
} | |
def isFriends1(user1: UserId, user2: UserId): Future[Either[Error, Boolean]] = | |
for{ | |
a <- followers(user1) | |
b <- followers(user2) | |
} yield for { | |
x <- a.right | |
y <- b.right | |
} yield x.exists(_.id == user2) && y.exists(_.id == user1) | |
def isFriends2(user1: UserId, user2: UserId): Future[Either[Error, Boolean]] = | |
followers(user1).flatMap{ | |
case Right(a) => | |
followers(user2).map{ | |
case Right(b) => | |
Right(a.exists(_.id == user2) && b.exists(_.id == user1)) | |
case Left(e) => | |
Left(e) | |
} | |
case Left(e) => | |
Future.successful(Left(e)) | |
} | |
} | |
object UsersRepositoryScalaz { | |
def followers(userId: UserId): EitherT[Future, Error, List[User]] = { | |
// 失敗した場合に、次のものが呼ばれるかどうか?をわかりやすくするために、printして、かつ失敗を固定で返す | |
println("call followers " + userId) | |
EitherT.left(Future.successful(UserNotFound(userId))) | |
} | |
def isFriends3(user1: UserId, user2: UserId): EitherT[Future, Error, Boolean] = | |
for{ | |
a <- followers(user1) | |
b <- followers(user2) | |
} yield a.exists(_.id == user2) && b.exists(_.id == user1) | |
} | |
object Main { | |
// ダミーの、単一スレッドでだけ使うExecutionContext | |
implicit val context: ExecutionContext = new ExecutionContext { | |
override def execute(runnable: Runnable): Unit = runnable.run() | |
override def reportFailure(t: Throwable): Unit = t.printStackTrace() | |
} | |
type UserId = Long | |
def main(args: Array[String]) { | |
println("isFriends1") | |
UsersRepository.isFriends1(0, 1) | |
println | |
println("isFriends2") | |
UsersRepository.isFriends2(0, 1) | |
println | |
println("isFriends3 scalaz") | |
UsersRepositoryScalaz.isFriends3(0, 1) | |
println | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment