Created
May 2, 2012 08:48
-
-
Save rirakkumya/2575219 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
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 | |
} | |
} | |
object Sample1 { | |
import SampleBase._ | |
def maternalGrandfather(sheep:Sheep):Option[Sheep] = mother(sheep) match { | |
case None => None | |
case Some(s) => father(s) | |
} | |
def mothersPaternalGrandfather(sheep:Sheep):Option[Sheep] = mother(sheep) match { | |
case None => None | |
case Some(s) => father(s) match { | |
case None => None | |
case Some(ss) => father(ss) | |
} | |
} | |
} | |
object Sample2 { | |
import SampleBase._ | |
case class Comb[a](x:Option[a]) { | |
def comb[b](f:a => Option[b]):Option[b] = x flatMap f | |
} | |
implicit def sheep2Comb(s:Option[Sheep]):Comb[Sheep] = Comb(s) | |
def mothersPaternalGrandfather(sheep:Sheep):Option[Sheep] = | |
Option(sheep) comb mother comb father comb father | |
} | |
object Main extends App { | |
val first = Sheep("1st",None,None) | |
val second = Sheep("2nd",Some(first),None) | |
val third = Sheep("3rd",Some(first),Some(second)) | |
val fourth = Sheep("4th",Some(second),Some(third)) | |
val fifth = Sheep("5th",Some(third),Some(fourth)) | |
for { s <- Sample1.maternalGrandfather(fifth) } assert(s.name == "2nd",s) | |
for { s <- Sample1.mothersPaternalGrandfather(fifth) } assert(s.name == "1st",s) | |
for { s <- Sample2.mothersPaternalGrandfather(fifth) } assert(s.name == "1st",s) | |
} |
単にこの場合に短く書くとしたら
case class Sheep(name:String,father:Option[Sheep],mother:Option[Sheep])
def maternalGrandfather(sheep:Sheep):Option[Sheep] = {
sheep.mother.flatMap{_.father}
}
def mothersPaternalGrandfather(sheep:Sheep):Option[Sheep] = {
sheep.mother.flatMap{_.father.flatMap{_.father}}
}
とかですかね
なるほど。その方が処理が分かりやすく、パフォーマンスの面でも有利ですね。
今思ったんですが、macroを使えばもう少しすっきり書けるような気がします。
例えば
nest"sheep.mother >> father >> father"
を
sheep.mother.flatMap{_.father.flatMap{_.father}}
に変換するのはどうでしょう。
nest型のcase classで汎用的に使えそうです。
文字リテラルなのでIDEの補完が効かないのは致命的ですが…
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ネタ元
http://www.sampou.org/haskell/a-a-monads/html/meet.html#example1