Created
April 14, 2012 05:55
-
-
Save rirakkumya/2382341 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
def index(id:String) = Action { | |
getFirstData(id) | |
} | |
private def getFirstData(id:String) = { | |
Cache.get(id) match { | |
case Some(id2) => getSecondData(id2) | |
case None => NotFound | |
} | |
} | |
private def getSecondData(id2:String) = { | |
Cache.get(id2) match { | |
case Some(result) => Ok(result) | |
case None => NotFound | |
} | |
} |
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 index(id:String) = Action { | |
Cache.get(id) match { | |
case Some(id2) => { | |
Cache.get(id2) match { | |
case Some(result) => Ok(result) | |
case None => NotFound | |
} | |
} | |
case None => NotFound | |
} | |
} |
たぶん後でunhappyになると思います…
一点だけ気になったので
case Some(r) if r.head == 'x' => Right("foo")
これは r == "" のときにNoSuchElementExceptionが飛ぶので、
case Some(r) if r.startsWith("x") => Right("foo")
にするべきでしょう。
確かに。ツッコミありがとうございます。
Action拡張すれば使い易くなりそう。 Right => Continue Left => Break でAlias切るか。 名前がイマイチだけど。良いネーミング無いかな。
forもscalazも使わずにシンプルに書けた
playで使うならこれが一番良さそう
case class Bind[a1,a2](x:Either[a1,a2]) {
def >>=[b](f:a2 => Either[a1,b]):Either[a1,b] = x.right flatMap f
}
implicit def either2Bind[a](s:Either[Result,a]) = Bind(s)
def index(id:String) = Action {
Right(id) >>= firstData >>= secondData >>= result merge
}
private def firstData(id:String) = {
Cache.get(id) match {
case Some(r) if r.startsWith("x") => Right("foo")
case Some(r) => Right(r)
case None => Left(NotFound)
}
}
private def secondData(id:String) = {
Cache.get(id) match {
case Some(r) if r == "badcode" => Left(BadRequest)
case Some(r) => Right(r)
case None => Left(NotFound)
}
}
private def result(id:String) = Right(Ok(id))
これでもいいけど、上の書き方の方が保守しやすいな
case class Bind[a1,a2](x:Either[a1,a2]) {
def >>=[b](f:a2 => Either[a1,b]):Either[a1,b] = x.right flatMap f
}
implicit def either2Bind[a](s:Either[Result,a]) = Bind(s)
def index(id:String) = Action {
Right(id) >>= { id =>
Cache.get(id) match {
case Some(r) if r.startsWith("x") => Right("foo")
case Some(r) => Right(r)
case None => Left(NotFound)
}
} >>= { id =>
Cache.get(id) match {
case Some(r) if r == "badcode" => Left(BadRequest)
case Some(r) => Right(r)
case None => Left(NotFound)
}
} >>= { r => Right(Ok(r)) } merge
}
https://github.com/scalaz/scalaz/blob/v7.0.0/core/src/main/scala/scalaz/Kleisli.scala#L15
Kleisli の合成だった
trait Response
case object BadRequest extends Response
case object NotFound extends Response
case class Ok(message: String) extends Response
object Cache{ def get(id: String): Option[String] = ??? }
import scalaz._,Scalaz._
val getOrNotFound = Kleisli[({type λ[+α]=Either[Response, α]})#λ, String, String]{
id => Cache.get(id) toRight NotFound
}
val getOrBad = Kleisli[({type λ[+α]=Either[Response, α]})#λ, String, String]{
id => Cache.get(id) toRight BadRequest
}
def index(id: String) = (getOrNotFound >=> getOrBad >=> getOrNotFound) run id map Ok merge
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
またつまらない茶々入れになってしまうのですが、get(First|Second)Data みたいなのは、下のように書くとハッピーかもしれません。