モナドはコンテナだ。リラックマもコンテナ(中身入ってるし)だ。
だったら、モナドはリラックマだ。
と言う訳で、リラックマでモナド則書いてみた。
まず、リラックマの実装。リラックマは、皮と中身がある。そもそもいない時もある。
まさにMaybeだ。なので、Optionにしてみる。
えぇ手抜きですとも。
package controllers | |
import play.api._ | |
import play.api.mvc._ | |
import play.api.cache._ | |
import play.api.Play.current | |
object Application extends Controller { | |
import EA._ | |
def index(id:String) = EitherAction {req => |
package controllers | |
import play.api._ | |
import play.api.mvc._ | |
import play.api.cache._ | |
import play.api.Play.current | |
object EA { | |
case class Bind[a1,a2](x:Either[a1,a2]) { | |
def #>>[b](f:a2 => Either[a1,b]):Either[a1,b] = x.right flatMap f |
case class Sheep(name:String,father:Option[Sheep],mother:Option[Sheep]) | |
object SampleBase { | |
def father(sheep:Sheep):Option[Sheep] = sheep match { | |
case Sheep(_, s, _) => s | |
case _ => None | |
} | |
def mother(sheep:Sheep):Option[Sheep] = sheep match { | |
case Sheep(_, _, s) => s | |
case _ => None |
libraryDependencies += "com.github.scala-incubator.io" %% "scala-io-core" % "0.3.0" | |
libraryDependencies += "com.github.scala-incubator.io" %% "scala-io-file" % "0.3.0" |
def foo[A,B](in:Option[A])(valid:PartialFunction[Option[A],Either[B,A]])(invalid:PartialFunction[Option[A],Either[B,A]])(other: =>Either[B,A]) = { | |
if(!valid.isDefinedAt(in) && !invalid.isDefinedAt(in)) { | |
other | |
}else{ | |
(valid orElse invalid)(in) | |
} | |
} | |
def getFirstData(id:String) = { | |
foo(Cache.get(id)){ |
libraryDependencies += "com.github.scala-incubator.io" %% "scala-io-core" % "0.3.0" | |
libraryDependencies += "com.github.scala-incubator.io" %% "scala-io-file" % "0.3.0" |
scala> for{(x,y) <- Right((3,4)).right} yield (x,y) | |
<console>:10: error: constructor cannot be instantiated to expected type; | |
found : (T1, T2) | |
required: Either[Nothing,(Int, Int)] | |
for{(x,y) <- Right((3,4)).right} yield (x,y) | |
scala> Right((3,4)).right map {case (x,y) => (x,y)} | |
res118: Product with Either[Nothing,(Int, Int)] with Serializable = Right((3,4)) |
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) = { |
import scala.annotation.tailrec | |
def hexToStr(s:String):String = { | |
@tailrec def r(target:String,result:String):String = { | |
target splitAt 2 match { | |
case (xx,xs) if !xx.isEmpty => r(xs,result + Integer.parseInt(xx,16).toChar) | |
case _ => result | |
} | |
} | |
r(s,"") | |
} |