颿°åããã°ã©ãã³ã°ã®ç ç©¶ãéå§ããå°éå®¶ã¯ãçšèªã®ãããŸãããšè€éãã®äž¡æ¹ã«çŽé¢ãããæ·±å»ãªæ°åŠããžã®èšåãåžžã«åãââãŠããŸãã
ãã®èšäºã§ã¯ãã«ããŽãªçè«ãšScalaã®é£è§£ãªèšèªã¡ã«ããºã ã䜿çšããã«ã2ã€ã®éèŠãªæŠå¿µãæ€èšããŸãã
- å
±å€ãã¡ã³ã¯ã¿ãŒ
- ã³ã³ãã©ããªã¢ã³ããã¡ã³ã¯ã¿ãŒ
å«ããããšãã§ããã«ããŽãªæ§é ã®ã»ããå
šäœãçè§£ããããã®åºçºç¹ã§ã
- ææ°ïŒäžå€ïŒãã¡ã³ ã¯ã¿ãŒ ã BiFunctor ã ProFunctor
- Applicative Functor ã Arrow ã Monad / Co-Monad
- ã¢ããå€æåš ã ã¯ã©ã€ã¹ãª ã èªç¶å€æ
ã«ããŽãªãŒçšèªã®èµ·æºã«ã€ããŠèª¬æããã«ããŽãªãŒæœè±¡åã®å®è£
ã«ãããèšèªã¡ã«ããºã ã®åœ¹å²ã瀺ããScalaæšæºã©ã€ãã©ãªãŒããã®ããã€ãã®å
±å€ïŒ
Option ã Try ã Future ã List ã Parser ïŒããã³åå€ïŒãã¡ã³
ãã£ã³ã° ã Equiv ïŒãã¡ã³ã¯ã¿ãŒãæ€èšããŸãã
ãã«ããŽãªã·ãªãŒãºãã®æåã®èšäºïŒ
- Scalaã®FPïŒãã¡ã³ã¯ã¿ãŒãšã¯ïŒ
- Scalaã®FPïŒInvariant Functor
Scalaãæ°åŠã颿°åããã°ã©ãã³ã°ã®äžçãããã«è©³ããç¥ãããå Žåã¯ã
Scala for Java Developersãªã³ã©ã€ã³ã³ãŒã¹ãã詊ããã ããïŒãããª+ãã¹ããäŸ¡æ Œã®ããã25ïŒ
ïŒïŒã
æœè±¡åã®èšèªã¡ã«ããºã ã«ã€ããŠ
åºæ¬çã«æ°ããããã°ã©ãã³ã°èšèªãžã®æ²¡å
¥ã«ã¯ã以äžã®åŠç¿ãå«ãŸããŸãã
- æ°ããã¿ã€ãã®æœè±¡åã®ããã®èšèªã¡ã«ããºã ã
- ãããã®ã¿ã€ãã®æœè±¡åã䜿çšãããå
žåçãªã€ãã£ãªã /ãã¿ãŒã³ã
äŸïŒOOPã¯ãã¯ã©ã¹ãã€ã³ã¹ã¿ã³ã¹ãç¶æ¿ãããªã¢ãŒãã£ãºã ãã«ãã»ã«åãå§ä»»ã...ããã³GoFèšèšãã¿ãŒã³ã®æŠå¿µã調æ»ããŸãããã®èšèšãã¿ãŒã³ã§ã¯ããã®ãããªããŸããŸãªæœè±¡åã¡ã«ããºã ããã¹ãŠäœ¿çšãããŸãã
ç§ã®æèŠã§ã¯ãç§»è¡Java => Scalaã®äž»ãªåé¡ã¯ãããã°ã©ããŒãæ°ããæœè±¡åã¡ã«ããºã ïŒããé«ãçš®é¡ã®ãžã§ããªãã¯ããã¹äŸååãåã¯ã©ã¹ããã¯ããªã©ïŒãåŠç¿ããªãããšã§ãã ã
ãããŠããæœè±¡åã®å¯Ÿè±¡ãïŒãã¡ã³ã¯ã¿ãŒãã¢ãããã¢ãã€ããåŸå±åãªã©ïŒã®è©±ãå§ãŸããšããã«ãçŸä»£æ°åŠïŒã«ããŽãªãŒçè«ãæœè±¡ä»£æ°ãæ°çè«çåŠïŒã®çè«å®¶ãçŸãã ãããŒããããã¹ãŠã®ããŒã¹ãã²ã£ããè¿ããŸããã ããã°ã©ããŒã®èгç¹ããã¯ãæ°åŠè
ã¯ãã°ãã°ãã«ããŽãªãŒã®å°æ¥ã®èšŒäººæŽŸ/åã®ãã¢ãããŒçè«/æ§æã®èšç®ã®çä¿¡è
ã®ããã«æ¯ãèããŸãïŒãç§ãã¡ã®èšèªã§ããšèšã£ãŠããã°ã©ãã³ã°ã®åéããå
·äœçãªäŸãäžããã®ã§ã¯ãªãã圌ãã¯æœè±¡æ°åŠã®èгç¹ããæ³šãã§ã圌ãã®è人ãåç
§ããŸã
ããã¹ããã®èšäºã§ã¯ããã¡ã³ã¯ã¿ãŒïŒå
±å€ããã³åå€ïŒã¯ãã«ããŽãªãŒçè«ã«é Œããã«åºæ¬çãªScalaã®ç¹åŸŽã®ã¿ã«åºã¥ããŠåæãããŸãã
ããé«ãçš®é¡ã® åã¯ã©ã¹ãš
ãžã§ããªãã¯ã¯äœ¿çšãããŸããïŒããšãã°ã
Scalazã©ã€ãã©ãªã®äœæè
ã¯ã
scala.scalaz.Functor +
scala.scalaz.Contravariant ãCatsïŒ
scala.cats.Functor +
cats.functor.Contravariant ãAlgebirdïŒ
comã twitter.algebird.Functor ïŒã å€ãã®å Žåãã€ãã£ãªã ã®å
±å€ãã¡ã³ã¯ã¿ãŒãšåå€ãã¡ã³ã¯ã¿ãŒã«å¯Ÿå¿ããåã®ååã§ã¯ãçç¥åïŒãã¡ã³ã¯ã¿ãŒãšåå€ïŒã䜿çšãããããšã«æ³šæããŠãã ããã
äžè¬çã«ãScalaã®é¢æ°åããã°ã©ãã³ã°ïŒL2ãL3ã¬ãã«ïŒã¯ãJavaã«å¯ŸããŠããã€ãã®æ¹åã®ãªãã»ããã§ãïŒ3ã€åç
§ïŒã ããã«ããªãã»ããã¯4ã€ã®ãã³ã³ããŒãã³ããã«ãã£ãŠåæã«ç¹åŸŽä»ããããŸãã
- æ°ããããã°ã©ãã³ã°ãã³ãã¬ãŒã/ã€ãã£ãªã /çç ã
- ãããã®ã€ãã£ãªã ãå®è£
ããããã®Scalaã®æ°ããèšèªãšã³ãžã³ã
- èšèªã¡ã«ããºã ã«åºã¥ãã€ãã£ãªã ã®å®è£
ãåããæ°ããScalaã©ã€ãã©ãªã
- ã€ãã£ãªã ã®éèŠãªã¢ã€ãã¢ã®ãœãŒã¹ãšããŠæ©èœããæ°åŠã®æ°ããã»ã¯ã·ã§ã³ã
ããã«æ³šæããå¿
èŠããããŸã
- ã€ãã£ãªã ãåŠã¶ããšã¯å¿
é ã§ã ïŒããããFPã³ã¢ãã§ãïŒã
- æœè±¡åã®èšèªã¡ã«ããºã ã®åŠç¿-åå©çšã«é©ããã€ãã£ãªã ãå®è£
ããããã«å®çšŒåã¢ãŒãã§å¿
èŠã§ã ã
- å
žåçãªScalaæ©èœã©ã€ãã©ãªã®ç ç©¶- ã§ããã°ãæ¢ã«äœæãããããã°ãããã€ãã£ãªã ãåå©çšããããã®å®çšŒåã¢ãŒãã§ã
- æ°åŠã®é¢é£ã»ã¯ã·ã§ã³ãå匷ããããšã¯ãã€ãã£ãªã ãçè§£ããã䜿çšãããããããã«å¿
èŠã§ã¯ãããŸãã ã
å°ãªããšããã3ã€ã®ã·ããããåºå¥ã§ããŸããã«ããŽãªãŒã代æ°ãè«çïŒæ°åŠã®ã»ã¯ã·ã§ã³ã®ååã«ããïŒ
ã€ãã£ãªã FP | Scalaã®ã¢ | Scalaã©ã€ãã©ãª | æ°åŠã®ã»ã¯ã·ã§ã³ |
---|
å
±å€ãã¡ã³ã¯ã¿ãŒãé©çšãã¡ã³ã¯ã¿ãŒãã¢ãããç¢å° | åã¯ã©ã¹ãäžäœã®ãžã§ããªã㯠| ã¹ã«ã©ãºãç« | ã«ããŽãªãŒçè« |
äŸåãã¢ãäŸå颿° | ãã¹äŸåå | 圢ã®ãªã | æ°åŠçè«ç |
ã¢ãã€ããã°ã«ãŒãããã£ãŒã«ãããªã³ã° | åã¯ã©ã¹ãäžäœã®ãžã§ããªã㯠| ã¢ã«ãžããŒããã¹ãã€ã¢ | ä»£æ° |
èŠããã«ïŒ
- äžäœçã®ãžã§ããªãã¯ã¯ ãåå©çšå¯èœãªæœè±¡åïŒå
±å€ãã¡ã³ã¯ã¿ãŒãªã©ïŒãæ§ç¯ããããã«äœ¿çšãããŸãã ãã®å ŽåãOOPã§ã¯ãå
ç¥ã¿ã€ããéåžžäœæãããŸãã
- åã¯ã©ã¹ã¯ãã³ãŒãã«ãæœè±¡åãé©çšãããããã«äœ¿çšãããŸãïŒãŠãŒã¶ãŒã¯ã©ã¹ã¯å
±å€ãã¡ã³ã¯ã¿ã«ããªããŸããïŒã ãã®å ŽåãOOPã§ã¯ããããã¯éåžžãç¥å
ã®æœè±¡åããç¶æ¿ãããŸãã
ç§ãã¡ã®äŸã§ã¯ãããé«ãking +åã¯ã©ã¹ã®ãžã§ããªãã¯ã䜿çšããªããããåå©çšã«é©åããŸããïŒãããŠãããã§ã®ãå€ãè¯ãOOPããªãã¯ãã¯ç¹ã«é©ããŠããŸããïŒã ããããåå©çšã®æºåãã§ããŠããªããŠãããã®äŸã¯ã€ãã£ãªã ã®æ¬è³ªããã瀺ããŠããŸãã
ã«ããŽãªãŒçè«ãšHaskellã«ã€ããŠ
20äžçŽåã°ã«ãæ°åŠã®æ°ããåéãçãŸããŸãã-ã«ããŽãªãŒçè«ïŒæ°åŠè
èªèº«ããã°ãã°
ãæœè±¡çãªãã³ã»ã³ã¹ããšåŒã¶ããšã«æ³šæããŠãã ããïŒã ã«ããŽãªçè«ã¯ãæ°åŠã®å€ãã®åºæ¬é åïŒéåè«ãããããžãŒãæ©èœåæãªã©ïŒã§åºã䜿çšãããŠããäžè¬çãªã¢ã€ãã¢/æ§é ããæ¥ãŠãããçŸåšããã¹ãŠã®æ°åŠã®åºç€/åºç€ã§ãããšäž»åŒµããŠããŸãïŒæ§ç¯ããéåè«ã®çŸ€éïŒ 20äžçŽåé ããã®æ°åŠïŒã
ããããéåè«ãéåèªäœïŒèŠçŽ ãéåã®æäœãéåã®ã«ãŒãã£ããªãã£ãæ§é ãæã€éåïŒé åºä»ãéåãéšåé åºéåïŒãªã©ïŒã«çŠç¹ãåãããŠããå Žåãéåã®ãããã³ã°ïŒéåããéåãžã®é¢æ°ïŒã¯èæ¯ã«ãããã«ããŽãªãŒçè«ã§ã¯ãåºç€ã¯ã«ããŽãªãŒã§ãããç°¡åã«èšãã°ã
category = set + mappingsã§ãã ãããã³ã°ã¯é¢æ°ã®å矩èªã§ãïŒããæ£ç¢ºã«ã¯ããããã³ã°=åŒæ°ããå€ã«çŽæ¥ãç§»åãããæé ãæå®ããã«å€ã®ãã¡ã€ã³ã®èŠçŽ ã®å®çŸ©ã®ãã¡ã€ã³ã®èŠçŽ ã«å¯Ÿå¿ããããã³ã°=ããŒãã«ã§æå®ããã颿°ããããã³ã°=
fã®æå³ã®é¢æ°ã®ãå€éšã€ã³ã¿ãŒãã§ã€ã¹ã
ïŒA => B ãå
éšå®è£
ãïŒé¢æ°æ¬äœïŒãæå®ããã«ïŒãããã§ã颿°èªäœã®ãããªåŒ·èª¿ã¯ã颿°åããã°ã©ãã³ã°ã«ãšã£ãŠéåžžã«éèŠã§ããããšãããããŸãã
ãããã³ã°ã«éäžãããšãè±å¯ãªæ©èœçæœè±¡åïŒãã¡ã³ã¯ã¿ãŒãã¢ãããªã©ïŒãçºçãããããã®æœè±¡åã¯é¢æ°åããã°ã©ãã³ã°èšèªïŒHaskellã§æãæåãªå®è£
ïŒã«è»¢éãããŸããã Scalaã®å€æãïŒ2005幎ãã2010幎ïŒã¯Haskellã®å€æãïŒ1990幎ãã1995幎ïŒã«æ¯ã¹ãŠ15幎éçžæ®ºãããå€ãã®ããšã¯HaskellããScalaã«æ¢è£œã§è»¢éãããŸãã ãããã£ãŠãScalaããã°ã©ããŒã«ãšã£ãŠã¯ãã«ããŽãªãŒçè«èªäœã§ã¯ãªããã«ããŽãªãŒæœè±¡åã®äž»ãªãœãŒã¹ãšããŠHaskellã®å®è£
ãæ±ãããšãããéèŠã§ãã ããã¯ãã«ããŽãªãŒçè«=> Haskellã®è»¢éäžã«ãå€ãã®éèŠãªè©³çްã倿Žãæ¶å€±ããŸãã¯è¿œå ããããšããäºå®ã«ãããã®ã§ãã ããã°ã©ããŒã«ãšã£ãŠéèŠã§ãããæ°åŠè
ã«ãšã£ãŠã¯äºæ¬¡çãªãã®ã§ãã
ç§»è¡ã®äŸã次ã«ç€ºããŸãã
- ã«ããŽãªãŒçè«ïŒ
- ãã¹ã±ã«ïŒ
- ScalaïŒScalazã©ã€ãã©ãªïŒ
å
±å€ãã¡ã³ã¯ã¿ãŒãšã¯
äžéšã®èè
ã¯ã
Covariant Functorãã³ã³ãããŒã«ããããšãæšå¥šã
ãŠããŸã ïŒããæ£ç¢ºã«
ã¯ãå
±å€Functorã¯ããããã³ã³ãããŒã®ååãã§ãïŒã ãã®æ¯phorãæãåºãããšããå§ãããŸãããå®çŸ©ã§ã¯ãªãæ¯preciselyãšããŠæ£ç¢ºã«æ±ããŸãã
Covariant Functorããèšç®ã³ã³ããã¹ããã§ããä»ã®äºº ã ããã¯çç£çãªã¢ãããŒãã§ãããã³ã³ã»ãããå®å
šã«ãã¹ã¿ãŒãããæå€§éã«æŽ»çšãããããšããå Žåã«åœ¹ç«ã¡ãŸãã ä»ã®ãšããç¡èŠããŠãã ããã
ããã«ä»ã®äººã¯ããããæ§æçãªã¢ãããŒãããææ¡ããŠããŸãã
Covariant Functorã¯ãç¹å®ã®ã¡ãœãããæã€ç¹å®ã®ã¿ã€ãã§ãã ã¡ãœããã¯ç¹å®ã®ã«ãŒã«ïŒ2ã€ïŒã«æºæ ããå¿
èŠããããŸãã
ãæ§æã¢ãããŒããã䜿çšããã³ã³ãã/ã¹ãã¬ãŒãžã®ã¡ã¿ãã¡ãŒã䜿çšããããšããå§ãããŸãã
ãæ§æçã¢ãããŒããã®èгç¹ããèŠããšãå
±å€ãã¡ã³ã¯ã¿ãŒã¯ã次ã®ã·ã°ããã£ãæã€ã¡ãœããïŒ
mapãšåŒã¶ïŒãæã€åãã©ã¡ãŒã¿ãŒãæã€ä»»æã®åïŒ
XãšåŒã¶ïŒãæã€åã§ãã
trait X[T] { def map(f: T => R): X[R] }
éèŠïŒãã®ç¹æ§ããç¶æ¿ããã®ã§ã¯ãªããé¡äŒŒã®ã¿ã€ããæ¢ããŸãã
ãæ§æçã¢ãããŒããã¯ãå€ãã®ã«ããŽãªæ§é ãäžè¬çãªã¹ããŒã ã«ãŸãšããããšãã§ãããšããç¹ã§åªããŠããŸã
trait X[T] {
éèŠïŒããã«ç€ºãããŠããã¡ãœããã¯ãããã€ãã®æœè±¡åã«å¿
èŠãªãã®ïŒå
±å€/åå€/ææ°é¢æ°ïŒãšãä»ïŒé©çšé¢æ°ãã¢ãããã³ã¢ãïŒã«å¿
èŠãªã¡ãœããã®1ã€ã§ãã
å
±å€ãã¡ã³ã¯ã¿ãŒã®äŸ
æ¢ã«ScalaïŒãŸãã¯Java 8ïŒã§ããã°ã©ãã³ã°ãéå§ããŠãã人ã¯ãããã«å
±å€ãã¡ã³ã¯ã¿ãŒã§ããå€ãã®ãã³ã³ãããŒã¿ã€ããã«ååãä»ããããšãã§ããŸãã
ãªãã·ã§ã³ import java.lang.Integer.toHexString object Demo extends App { val k: Option[Int] = Option(100500) val s: Option[String] = k map toHexString }
ãŸãã¯äººçã«å°ãè¿ã
import java.lang.Integer.toHexString object Demo extends App { val k: Option[Int] = Map("A" -> 0, "B" -> 1).get("C") val s: Option[String] = s map toHexString }
ã詊ããã ãã import java.lang.Integer.toHexString import scala.util.Try object Demo App { val k: Try[Int] = Try(100500) val s: Try[String] = k map toHexString }
ãŸãã¯äººçã«å°ãè¿ã
import java.lang.Integer.toHexString import scala.util.Try object Demo extends App { def f(x: Int, y: Int): Try[Int] = Try(x / y) val s: Try[String] = f(1, 0) map toHexString }
æªæ¥ import java.lang.Integer.toHexString import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future object Demo extends App { val k: Future[Int] = Future(100500) val s: Future[String] = k map toHexString }
ãŸãã¯äººçã«å°ãè¿ã
import java.lang.Integer.toHexString import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future object Demo extends App { def calc: Int = (0 to 1000000000).sum val k: Future[Int] = Future(calc) val s: Future[String] = k map toHexString }
äžèЧ import java.lang.Integer.toHexString object Demo extends App { val k: List[Int] = List(0, 42, 100500) val s: List[String] = k map toHexString }
ããŒãµãŒ import java.lang.Integer.toHexString import scala.util.parsing.combinator._ object Demo extends RegexParsers with App { val k: Parser[Int] = """(0|[1-9]\d*)""".r ^^ { _.toInt } val s: Parser[String] = k map toHexString println(parseAll(k, "255")) println(parseAll(s, "255")) } >> [1.4] parsed: 255 >> [1.4] parsed: FF
äžè¬ã«ãäŸãšããŠå€æãããšãã³ã³ãããšããŠã®å
±å€ãã¡ã³ã¯ã¿ãŒã®æ¯phorã¯æ©èœããŸãã æ¬åœã«
- ãªãã·ã§ã³-1ã€ã®èŠçŽ ã®ãã³ã³ããã®ããã«ããäœããååšããå¯èœæ§ãããïŒäžéšïŒãŸãã¯ããã§ãªãå¯èœæ§ãããïŒãªãïŒ
- 詊ããŠã¿ãŠãã ãã-ããèŠçŽ ã«ãã³ã³ããã®ããã«ããã©ãã«ãããïŒæåïŒãŸãã¯ããã§ãªããããããŸããïŒå€±æãããæ£ç¢ºã«ã¯ãèŠçŽ ã®ä»£ããã«äŸå€ããããŸãïŒã
- æªæ¥-äœãããã§ã«ãããããããªããããããããã€ããŠãããããããªããäŸå€ãæ¢ã«ããããŸãã¯äŸå€ããããã€ãããŸãã¯æ±ºããŠãããã€ããªããã³ã³ããã®ãããªãèŠçŽ ã
- ãªã¹ã-0ãNåã®èŠçŽ ãããã³ã³ãã
- ããŒãµãŒã¯ããã§ã¯ããå°ãè€éã§ãäœããæ ŒçŽããããŠããŸãããããŒãµãŒã¯æååããããŒã¿ãæœåºããæ¹æ³ã§ãã ãã ããããŒãµãŒã¯ããŒã¿ãœãŒã¹ã§ããããã®ç¹ã§ã¯ã³ã³ãããŒã«äŒŒãŠããŸãã
å
±å€ãã¡ã³ã¯ã¿ãŒã¯ãç¹å®ã®ã·ã°ããã£ãæã€ã¡ãœããã®ååšã ãã§ãªãã2ã€ã®ã«ãŒã«ã®å±¥è¡ã§ããããŸãã ããã§ã®æ°åŠè
ã¯éåžžã«ããŽãªãŒçè«ãåç
§ãããããã®èŠåã¯
ãã¡ã³ã¯ã¿ãŒãã«ããŽãªãŒæºååã§ãããšããäºå®ã®çµæã§ãããšèšããŸããã€ãŸããæ§é ãä¿æããã«ããŽãªãŒãžã®ã«ããŽãªãŒã®ãããã³ã°ã§ãïŒãããŠåäžç¢å°èŠçŽ ã¯ã«ããŽãªãŒæ§é ã®äžéšã§ãïŒæçåèŠåïŒããã³ç¢å°ã®æ§æèŠåïŒæ§ææ³ïŒïŒã
ãã®ã¢ãããŒãã¯ãäžè¬çã«ããã°ã©ãã³ã°ã§ã¯éçç£çã§ãã 颿°åããã°ã©ãã³ã°ã§ã¯ãæ©èœãç¶æããªããïŒéåžžã¯æé©åã®ç®çã§ïŒããã°ã©ã ã倿ããããã«ãããã2ã€ã®ã«ãŒã«ãå¿
èŠã§ããããšãèæ
®ããŠãã ããã
å
±å€é¢æ°ïŒã¢ã€ãã³ãã£ãã£æ³
å
±å€ã®æ¥œãããã¡ã³ã¯ã¿ãŒã®å Žåãæ¬¡ã®ã«ãŒã«IdentityLaw.case0ïŒfunïŒãåäžã«å®è¡ããå¿
èŠããããŸã-IdentityLaw.case1ïŒfunïŒãšåãã§ãã
object IdentityLaw { def case0[T](fun: Functor[T]): Functor[T] = identity(fun) def case1[T](fun: Functor[T]): Functor[T] = fun.map(identity) }
ããã§ãidentityã¯Predef.scalaããã®å€æ
çãªåäžæ§é¢æ°ïŒåäœé¢æ°ïŒã§ã
object Predef ... { def identity[A](x: A): A = x ... }
ããªãç°¡åã«-fun.mapïŒidentityïŒã¯ãã¡ã³ã¯ã¿ãŒå
ã®äœã倿Žãã¹ãã§ã¯ãããŸããã
ããã¯ãããŒãžã§ã³ãä¿åããåãã£ã¹ãã¬ã€ã§ããŒãžã§ã³ãå¢ããã³ã³ããããå
±å€ãã¡ã³ã¯ã¿ãŒã®äžäœã«å¯Ÿå¿ããªãããšãæå³ããŸã
衚瀺æäœã®åæ°ããã«ãŠã³ããããããïŒã¢ã€ãã³ãã£ãã£é¢æ°ã«ãã衚瀺ãïŒã
ãããããã®ãããªã³ãŒãã¯ãã¡ã³ã¯ã¿ãŒã®æåã®ã«ãŒã«ã«å¯Ÿå¿ããŠããŸãïŒ2çªç®ã®ã«ãŒã«ã«ã察å¿ããŠããŸãïŒã
ããã§ã¯ãããŒãžã§ã³ã¯ããŒã¿ã«åçŽã«æ·»ä»ããã衚瀺æã«åžžã«ä»éããŸãã
å
±å€ãã¡ã³ã¯ã¿ãŒïŒåææ³
å
±å€ãã¡ã³ã¯ã¿ãŒ 'fun [T]'ããã³é¢æ° 'fïŒ'ããã³ 'g'ã®å Žåãæ¬¡ã®ã«ãŒã«CompositionLaw.case0ïŒfunïŒãåäžã«å®è¡ããå¿
èŠããããŸã-CompositionLaw.case1ïŒfunïŒãšåãã§ãã
object Lawompose extends App { def case0[T, R, Q](fun: Functor[T], f: T => R, g: R => Q): Functor[Q] = (fun map f) map g def case1[T, R, Q](fun: Functor[T], f: T => R, g: R => Q): Functor[Q] = fun map (f andThen g) }
ã€ãŸãã颿°ãfãã§ã次ã«é¢æ°ãgãã§é çªã«è¡šç€ºãããä»»æã®ãã¡ã³ã¯ã¿ãŒã³ã³ãããŒã¯ã颿°fãšgïŒf andThen gïŒã®æ°ãã颿°æ§æãäœæããããã1å衚瀺ããããšãšåçã§ãã
äŸãèããŠã¿ãŸãããã ã³ã³ãããŒã¯ãã°ãã°ãã¡ã³ã¯ã¿ãŒãšèŠãªãããããããã¡ã³ã¯ã¿ãŒãååž°çãªããŒã¿åïŒãã€ããªããªãŒåã³ã³ãããŒïŒã«ããŸãããã
sealed trait Tree[T] { def map[R](f: T => R): Tree[R] } case class Node[T](value: T, fst: Tree[T], snd: Tree[T]) extends Tree[T] { def map[R](f: T => R) = Node(f(value), fst map f, snd map f) } case class Leaf[T](value: T) extends Tree[T] { def map[R](f: T => R) = Leaf(f(value)) }
ããã§ãmapã¡ãœããïŒfïŒT => RïŒã¯ã颿° 'f'ãåãªãŒããŸãã¯ããŒãïŒãªãŒããããŒãïŒã®ã¿ã€ã 'T'ã®èŠçŽ ã«é©çšããããŒãïŒããŒãïŒã®åå«ã«ååž°çã«äŒæããŸãã ã ããç§ãã¡ã¯
- ããªãŒæ§é ãä¿æãããŸã
- ãæšã«æãã£ãŠãããããŒã¿ã®å€ãå€åãã
ãããã³ã°äžã«ããªãŒã®æ§é ã倿Žããããšãããšãäž¡æ¹ã®èŠåã«éåããŸãïŒIdentity LawãšComposition Lawã®äž¡æ¹ïŒã
ãã¡ã³ã¯ã¿ã§ã¯ãããŸããïŒåããŒãã®åå«ã衚瀺ãããšãã«ã¹ã¯ããããŸã
case class Node[T](value: T, fst: Tree[T], snd: Tree[T]) extends Tree[T] { def map[R](f: T => R) = Node(f(value), snd map f, fst map f) }
ãã¡ã³ã¯ã¿ã§ã¯ãããŸããïŒãã£ã¹ãã¬ã€ããšã«ããªãŒãæé·ããèãæã«å€ãããŸã
case class Leaf[T](value: T) extends Tree[T] { def map[R](f: T => R) = Node(f(value), Leaf(f(value)), Leaf(f(value))) }
ãã®ãããªïŒèª€ã£ãïŒãã€ããªããªãŒã®å®è£
ããã¡ã³ã¯ã¿ãŒãšããŠèŠããšãããŒã¿ã®è¡šç€ºãšãšãã«ãããªãŒã®æ§é ã倿Žãã圢ã§mapã®äœ¿çšåæ°ãã«ãŠã³ãããŠããããšãããããŸãã ããã§ãã¢ã€ãã³ãã£ãã£ã«åå¿ããfãšgã®ããã€ãã®äœ¿çšæ³ã¯ãfãšgã®äœ¿çšæ³ãšã¯ç°ãªããŸãã
å
±å€ãã¡ã³ã¯ã¿ãŒïŒæé©åã«äœ¿çš
å
±å€ãã¡ã³ã¯ã¿ãŒã®å
¬çã®å©ç¹ã瀺ãäŸãèŠãŠã¿ãŸãããã
ãããã³ã°ãšããŠãæŽæ°äžã®ç·åœ¢é¢æ°ãèããŸã
case class LinFun(a: Int, b: Int) { def apply(k: Int): Int = a * k + b def andThen[A](that: LinFun): LinFun = LinFun(this.a * that.a, that.a * this.b + that.b) }
T => Rã®åœ¢åŒã®æãäžè¬çãªé¢æ°ã®ä»£ããã«ããããã®ãµãã»ããã䜿çšããŸããäžè¬çãªåœ¢åŒãšã¯ç°ãªããæç€ºçãªåœ¢åŒã§ç·åœ¢é¢æ°ã®æ§æãæ§ç¯ã§ãããããIntäžã®ç·åœ¢é¢æ°ã§ãã
ãã¡ã³ã¯ã¿ãšããŠãåçŽã«æŽæ°ã®ãªã¹ããé£çµããã¿ã€ãã®ååž°ã³ã³ããïŒIntïŒãæ€èšããŸã
sealed trait IntSeq { def map(f: LinFun): IntSeq } case class Node(value: Int, tail: IntSeq) extends IntSeq { override def map(f: LinFun): IntSeq = Node(f(value), tail.map(f)) } case object Last extends IntSeq { override def map(f: LinFun): IntSeq = Last }
ãããŠä»ããã¢
object Demo extends App { val seq = Node(0, Node(1, Node(2, Node(3, Last)))) val f = LinFun(2, 3)
ç§ãã¡ã¯ã©ã¡ãã
- ãªã¹ãã®ãã¹ãŠã®èŠçŽ ã2åç¹°ãè¿ããŸãïŒ2åã¯ã¡ã¢ãªãééããŸãïŒ
- ç®è¡æŒç®ãå®è¡ããããã«2åïŒ*ããã³+ïŒ
ã³ã³ããžã·ã§ã³fããã³gãæ§ç¯ãã
- ãªã¹ãã®ãã¹ãŠã®èŠçŽ ã1åç¹°ãè¿ã
- ç®è¡æŒç®ã1åå®è¡ãã
åå€ãã¡ã³ã¯ã¿ãŒãšã¯
ç¹å®ã®ã·ã°ããã£ïŒæ¡ä»¶ä»ãã§
mapãšåŒã°ããïŒãæã¡ãç¹å®ã®ã«ãŒã«ïŒ
Identity Law ã
Composition Law ïŒã«åŸãã¡ãœãããæã€ãã¹ãŠã®ã¯ã©ã¹
Xã¯å
±å€ãã¡ã³ã¯ã¿ãŒãšåŒã°ããããšãæãåºãããŠãã ãã
trait X[T] { def map[R](f: T => R): X[R] }
åæ§ã«ãç¹å®ã®çœ²åãæã¡ãç¹å®ã®èŠåïŒãããã¯
Identity Law ã
Composition LawãšãåŒã°ã
ãŸã ïŒãæã€ã¡ãœããïŒæ¡ä»¶ä»ãã§
contramap ïŒãæã€ãã¹ãŠã®ã¯ã©ã¹
Xã¯ãåå€ãã¡ã³ã¯ã¿ãŒãšåŒã°ããŸãã
trait X[T] { def contramap[R](f: R => T): X[R] }
ãã®æç¹ã§ãåœæãããªãŒããŒã忢ããå ŽåããããŸãã åŸ
ã£ãŠãã ããããã ãã
Tãå«ãã³ã³ãããããã颿°
fïŒT => RãååŸããå Žåã
Rãå«ãã³ã³ãããååŸããæ¹æ³ã¯æããã§ã
ã 颿°ãã³ã³ããã«æž¡ãã颿°ãã³ã³ããå
ã«æµžããèŠçŽ ãåé€ããã«é¢æ°ãé©çšããŸãã ãã ãã
Tãå«ãã³ã³ãããæã¡ã颿°
fïŒR => Tãåãåãæ¹æ³ããéé ãã§é©çšããæ¹æ³ã¯å®å
šã«çè§£äžèœã§ãã
äžè¬çãªæ°åŠã§ã¯ããã¹ãŠã®é¢æ°ã«é颿°ãããããã§ã¯ãªããé颿°ãååšããå Žåã§ããããèŠã€ããäžè¬çãªæ¹æ³ã¯ãããŸããã ããã°ã©ãã³ã°ã§ã¯ã建èšçã«è¡åããå¿
èŠããããŸãïŒååšãäžææ§ãªã©ã§æ©èœããã ãã§ãªããæ§æãæ§ç¯ããŠå®è¡ããŸãïŒ-äœããã®æ¹æ³ã§é¢æ°
fãæ§ç¯ããå¿
èŠããããŸã
ïŒR => T颿°
gïŒT => Rã³ã³ããã®å
容ïŒ
ãããŠãããã§ç§ãã¡ã®æ¯phorïŒå
±å€é¢æãã³ã³ããïŒãæ©èœããªãããšãããããŸãã çç±ãèŠãŠã¿ãŸãããã
ãã¹ãŠã®ã³ã³ããã«ã¯2ã€ã®æäœãå«ãŸããŸã
- put-ã³ã³ããã«ã¢ã€ãã ãå
¥ããŸã
- get-ã³ã³ããããã¢ã€ãã ãæœåºããŸã
ãã ããæ€èšãããŠããäŸïŒOptionãTryãFutureãListãParserïŒã«ã¯ãããçšåºŠgetã¡ãœããããããŸãããputã¡ãœããã¯ãããŸããïŒ Option / Try / Futureã§ã¯ãèŠçŽ ã¯ã³ã³ã¹ãã©ã¯ã¿ãŒïŒãŸãã¯ã³ã³ãããªã³ãªããžã§ã¯ãã®applyã¡ãœããïŒãŸãã¯äœããã®ã¢ã¯ã·ã§ã³ã®çµæãšããŠååŸãããŸãã Parser [T]-Tã®è¡ãããªãµã€ã¯ã«ããããããParserã«ã¯ãŸã£ããã¢ã¯ã»ã¹ã§ããŸãã
ãParser[T]ã¯ã¹ãã¬ãŒãžã§ã¯ãªãTã®ãœãŒã¹ã§ãïŒãããŠãããã«é metaã®èª€ãã®ç§å¯ããããŸãã
å
±å€ãã¡ã³ã¯ã¿ãŒã¯ã³ã³ãããŒã®ååã§ãã ããŒã¿ã®ååŸãæ
åœããéšåããã€ã¢ã°ã©ã ã«æããŠã¿ãŸããã
+ ------------------------- +
| + ------ + T | R
| | X [T] -----> fïŒT => R ---->
| + ------ + |
+ ------------------------- +
ã€ãŸããå
±å€ãã¡ã³ã¯ã¿ãŒã®åºå£ã§ã¯ãã¿ã€ã
Tã®ããŒã¿èŠçŽ ã¯é¢æ°
fïŒT => RãåŸ
æ©ãããã®æ§æã¯ã
Rã§å
¥åãããå
±å€ãã¡ã³ã¯ã¿ãŒã§ã
ããã®å Žåãã¹ãã¬ãŒãžã³ã³ãããŒã§ã¯ãªãçç±ãæããã«ãªããŸãããäžè¬çãªIteratorããã³StreamããŒã¿ãœãŒã¹ãå
±å€ãã¡ã³ã¯ã¿ãŒã§ãã
???
???
æŠç¥çã«ã¯ãå
±å€ãã¡ã³ã¯ã¿ãŒã¯æ¬¡ã®ãšããã§ãã倿
fãããã蟌ã¿ã
ãŸããR=> T㯠ãåºåãã§ã¯ãªããå
¥åãã§ãã
+ ------------------------- +
R | T + ------ + |
-----> fïŒR => T -----> X [T] | |
| + ------ + |
+ ------------------------- +
åå€ãã¡ã³ã¯ã¿ãŒã®äŸ
Scalaæšæºã©ã€ãã©ãªã§åå€ãã¡ã³ã¯ã¿ãŒã®äŸãæ€çŽ¢ããã«ã¯ãã³ã³ãããŒã¡ã¿ãã¡ãŒãå¿ããŠãåŒæ°ãšããŠããŒã¿ã®ã¿ãåãå
¥ãã颿°ã®çµæãè¿ããªã1ã€ã®åãã©ã¡ãŒã¿ãŒãæã€åãæ¢ãå¿
èŠããããŸãã
äŸã¯ã
泚æãš
åçã§ãäŸïŒ
泚æ import scala.math.Ordering._ object Demo extends App { val strX: Ordering[String] = String val f: (Int => String) = _.toString val intX: Ordering[Int] = strX on f }
æååãçžäºã«æ¯èŒããæ¹æ³ãæã¡ãæŽæ°ãæååã«å€æããæ©èœãæã€ããšã§ãæ°å€ãæååãšããŠæ¯èŒããæ¹æ³ãæ§ç¯ã§ããŸãã
è¡ã«é¢ããç°¡åãªã³ã¡ã³ã
val strX: Ordering[String] = String
ãã®å Žåãjava.lang.Stringã§ã¯ãªããscala.math.Ordering.String
package scala.math trait Ordering[T] extends ... { trait StringOrdering extends Ordering[String] { def compare(x: String, y: String) = x.compareTo(y) } implicit object String extends StringOrdering ... }
onã¡ãœããã¯
contramapã¡ãœããã§ã
package scala.math trait Ordering[T] extends ... { def on[R](f: R => T): Ordering[R] = new Ordering[R] { def compare(x: R, y: R) = outer.compare(f(x), f(y)) } ... }
äŸïŒ
åç import java.lang.String.CASE_INSENSITIVE_ORDER import scala.math.Equiv import scala.math.Equiv.{fromFunction, fromComparator} object Demo extends App { val strX: Equiv[String] = fromComparator(CASE_INSENSITIVE_ORDER) val f: (Int => String) = _.toString val intX: Equiv[Int] = fromFunction((x, y) => strX.equiv(f(x), f(y))) }
java.lang.String.CASE_INSENSITIVE_ORDERã³ã³ãã¬ãŒã¿ã¡ãœããã«åºã¥ããŠãæå忝èŒã¡ãœããïŒscala.math.Equizã®ç䟡é¢ä¿ïŒãæ§ç¯ããŠããŸãã
package java.lang; public final class String implements ... { public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator(); private static class CaseInsensitiveComparator implements Comparator<String>, java.io.Serializable { public int compare(String s1, String s2) {...} ... } ... }
fromComparatorã¡ãœããã䜿çšãã
object Equiv extends ... { def fromComparator[T](cmp: Comparator[T]): Equiv[T] = new Equiv[T] { def equiv(x: T, y: T) = cmp.compare(x, y) == 0 } ... }
ã³ã³ãã©ãããã¡ãœããã®ä»£ããã«ãfromFunctionã¡ãœããã«åºã¥ãé¢åãªæ§é ã䜿çšããŸã
object Equiv extends ... { def fromFunction[T](cmp: (T, T) => Boolean): Equiv[T] = new Equiv[T] { def equiv(x: T, y: T) = cmp(x, y) } ... }
åå€é¢æ°ïŒã¢ã€ãã³ãã£ãã£æ³
å
±å€ãã¡ã³ã¯ã¿ãŒã®å Žåã®ããã«ãåå€ãã¡ã³ã¯ã¿ãŒã¯ã眲åä»ãã®ã¡ãœããã«å ããŠã2ã€ã®ã«ãŒã«ã«åŸãå¿
èŠããããŸãã
æåã®èŠåïŒåäžæ§æ³åïŒã«ã¯ãåå€
ãã¡ã³ã¯ã¿ãŒã®å ŽåãIdentityLaw.case0ïŒfunïŒã¯åäžã§ãªããã°ãªãããIdentityLaw.case1ïŒfunïŒã§ãªããã°ãªããŸãã
object IdentityLaw { def case0[T](fun: Contravariant[T]): Contravariant[T] = identity(fun) def case1[T](fun: Contravariant[T]): Contravariant[T] = fun.contramap(identity) }
ã€ãŸããåå€ãã¡ã³ã¯ã¿ãŒãšåäœé¢æ°ã®ãããã³ã°ã¯ããã倿ŽããŸããã
åå€ãã¡ã³ã¯ã¿ãŒïŒåææ³
2çªç®ã®ã«ãŒã«ïŒæ§ææ³ïŒã«ãããšãåå€ãã¡ã³ã¯ã¿ãŒ
[T]ããã³é¢æ°
fïŒQ => Rããã³
gïŒR => Tã®ä»»æã®ãã¢ã®å Žå
ããã®ãã¢ã¯IdentityLaw.case1ïŒfunïŒãšåäžã®IdentityLaw.case0ïŒfunïŒã§ãªããã°ãªããŸãã
object CompositionLaw { def case0[Q, R, T](fun: Contravariant[T], f: Q => R, g: R => T): Contravariant[Q] = (fun contramap g) contramap f def case1[Q, R, T](fun: Contravariant[T], f: Q => R, g: R => T): Contravariant[Q] = fun contramap (f andThen g) }
ã€ãŸãã颿°ã®ãã¢ã«ããåå€ãã¡ã³ã¯ã¿ãŒã®é 次ãããã³ã°ã¯ã颿°ã®æ§æïŒå転ïŒã«ãããŠããããããã³ã°ãšåçã§ãã
次ã¯ïŒ
å
±å€ããã³åå€ãã¡ã³ã¯ã¿ãŒã®æŠå¿µã¯ã颿°åããã°ã©ãã³ã°ã«ãããã«ããŽãªçè«ããã®æœè±¡åã®äœ¿çšã«é¢ããçå£ãªç ç©¶ã®åºçºç¹ã«ãããŸããïŒScalaã®çšèª-Catsã©ã€ãã©ãªã®Scalazã®äœ¿çšãžã®ç§»è¡ïŒã
远å ã®æé ã¯æ¬¡ã®ãšããã§ãã
- å
±å€ããã³åå€ã®ãã¡ã³ã¯ã¿ãŒïŒBiFunctorãProFunctorãExponentialïŒInvariantïŒFunctorïŒã®æ§æã®ç ç©¶
- ããç¹æ®ãªæ§é ïŒApplicative FunctorãArrowãMonadïŒã®ç ç©¶ãããã¯ãèšç®ãå
¥åºåããšã©ãŒåŠçãç¶æ
ã®å€åãæ±ãæ°ãããã©ãã€ã ããã§ã«å®éã«æ§æããŠããŸãã å°ãªããšãããã¹ãŠã®ã¢ããã¯å
±å€ãã¡ã³ã¯ã¿ãŒã§ããããšãææããŸãã
æ®å¿µãªãããèšäºã®ãµã€ãºã§ã¯ãäžåºŠã«ãã¹ãŠãäŒããããšã¯ã§ããŸããã
PSãã®èšäºãæåŸãŸã§èªãã 人ã®
ããã« ã
Scala for Java Developersã³ãŒã¹
ãäŸ¡æ Œã®25ïŒ
ã§æäŸããŠããŸãïŒãªã³ã¯ããã©ããã
HABR-COVARIANT-FUNCTORã¯ãŒãã³ã䜿çšããŠ
ãã ãã ïŒã å²åŒã¯ãŒãã³ã®æ°ã¯éãããŠããŸãïŒ