Either 㨠scalaz.Validation
ä¸è¨ã§åãä¸ãããã¦ãããã¿ã«ã¤ãã¦ã¡ã¢ãæ®ãã
Either 㨠Scalaz
Either 㯠flatMap ã¡ã½ãããæããªãã®ã§ for å¼ã§ã¯ä½¿ããªããfor å¼å 㧠Right ã§å¦çãé²ããããªã right ã¡ã½ããã§ãLeft ã§å¦çãé²ããããªã left ã¡ã½ãã㧠*Projection ãåå¾ããå¿ è¦ãããã
def r(n: Int): Either[String, Int] = Right(n) for { x <- r(1).right; y <- r(x).right } yield x+y
ã¨ã¯ãããå¤ãã®å ´å Right ã§å¦çãé²ãããå ´åãå¤ããLeft ã§å¦çãé²ãããäºã¯ç¨ã§ãããå¿æ çã«ã¯ãä¸è¨ã®ããã«æ¸ãããã
def r(n: Int): Either[String, Int] = Right(n) for {x <- r(1); y <- r(x)} yield x+y
ãã㧠scalaz ã®åºçªã¨ãªããä¸è¨ã¯ãåé¡ãªãåä½ããã
import scalaz._ import Scalaz._ def r(n: Int): Either[String, Int] = Right(n) for { x <- r(1); y <- r(x) } yield x+y
以éã®ãµã³ãã«ã³ã¼ãã¯ãä¸è¨ã®ããã« scalaz ã import æ¸ã¿ã§ããäºãå¿ é ã¨ããã
import scalaz._ import Scalaz._
scalaz ã使ã£ã¦ããã®ã§ãä¸è¨ã®ããã«ãæ¸ããã
for { x <- 1.right[String]; y <- x.right[String] } yield x+y
ããããflatMap 㨠map ã使ã£ãå½¢å¼ã«æ¸ãæããã¨ä¸è¨ã®éãã
1.right[String] flatMap {x => x.right[String] map {y => x + y}}
scalaz ã§ã¯ä¸è¨ã®ã¨ã¤ãªã¢ã¹ã使ããã
1.right[String] >>= {x => x.right[String] ∘ {y => x + y}}
&#8728; 㯠∘ ã§ã
scalaz.Validation
å®ã¯ãfor å¼ã®ä¸ã§ä½¿ãåã«ã¯ãEither ã¨å¤ãããªãã
(for {x <- 1.success[String]; y <- x.success[String]} yield x+y) assert_=== 2.success[String] (for {x <- "foo".fail[Int]; y <- x.success[String]} yield x+y) assert_=== "foo".fail[Int]
scalaz.Validation ã® flatMap 㨠map ã®ã½ã¼ã¹ã³ã¼ãã¯ãç¾å¨ã®æãä¸è¨ã®éãã¨ãªã£ã¦ããã®ã§ãä¸è¨ã¯å½ããåã
//..snip.. def map[B](f: A => B): Validation[E, B] = this match { case Success(a) => Success(f(a)) case Failure(e) => Failure(e) } //..snip.. def flatMap[EE >: E, B](f: A => Validation[EE, B]): Validation[EE, B] = this match { case Success(a) => f(a) case Failure(e) => Failure(e) } //..snip..
ã§ã¯ãEither 㨠Validation ã®éãã¯ä½ãªã®ãï¼ä¸è¨ã®ãããªã³ã¼ããè¨è¿°ããéã«éããç¾ããã
(1.success[String] <*> (1.success[String] map ((_: Int) + (_: Int)).curried)) assert_=== 2.success[String] ("foo".fail[Int] <*> (1.success[String] <*> ("bar".fail[Int] map ((_: Int) + (_: Int) + (_: Int)).curried))) assert_=== "barfoo".fail[Int]
å
¨ã¦ã Success ã®éã«ã¯ map ã§ç¹ãã é¢æ°ãè©ä¾¡ãããFailure ã®å ´åã¯å
å
ããã¦ããå¤ãç©ã¿éãªã£ã¦ãããbar ãåã«ããããè©ä¾¡é ã¯å·¦ããå³ã
Validation ã¯ãMonad ã§ãããªãã° Applicative ã§ãããã®ã§ Validation[A => B] ãå¼æ°ã«åã <*> ã¡ã½ãããæã¤ã
å®éã« Failure ãç©ã¿éãã¦ããç®æ㯠Apply.scala å
ã®ä¸è¨ã
implicit def ValidationApply[X: Semigroup]: Apply[({type λ[α]=Validation[X, α]})#λ] = new Apply[({type λ[α]=Validation[X, α]})#λ] { def apply[A, B](f: Validation[X, A => B], a: Validation[X, A]) = (f, a) match { case (Success(f), Success(a)) => success(f(a)) case (Success(_), Failure(e)) => failure(e) case (Failure(e), Success(_)) => failure(e) case (Failure(e1), Failure(e2)) => failure(e1 ⊹ e2) } }
&#8889; 㯠⊹ ã§ã
Failureå´(å·¦å´)ã® X ãå群(Semigroup)ã§æç¸ããæ°ããåã³ã³ã¹ãã©ã¯ã¿ãåå¼æ°ã¨ãã¦ä¸ãã Apply ã new ãã¦ãããå群ãªã®ã§ãå½ç¶ãäºé
æ¼ç® ⊹(|+| ã§ãè¯ã) ãæã£ã¦ããã
ã¡ãªã¿ã«ã({type λ[α]=Foo[X, α]})#λãã¯ãX ãæç¸ããæ°ããç¡ååã³ã³ã¹ãã©ã¯ã¿ãä½ãå®åæã¨ãã¦è¦ãã㨠scalaz ã®ã³ã¼ããèªã¿ããããªãã
å¹¾ã¤ããæ¸ãæãã®ä¾ã示ãã
("foo".fail[Int].<***>(1.success[String], "bar".fail[Int]) {_ + _ + _}) assert_=== "foobar".fail[Int] (("foo".fail[Int] |@| 1.success[String] |@| "bar".fail[Int]) {_ + _ + _}) assert_=== "foobar".fail[Int] (("foo".fail[Int] ⊛ 1.success[String] ⊛ "bar".fail[Int]) {_ + _ + _}) assert_=== "foobar".fail[Int]
&#8859; 㯠⊛ ã§ã
ä¸è¨ã®å ´åãè©ä¾¡é 㯠<*> åæ§ã«å·¦ããå³ãçµæ㯠<*> ã¨éé ããã¡ãã®æ¹ãè¦ãç®ãçµæã解ãããããä½æ
ãããããªçµæã«ãªããã¯â¦ MA.scala ã®å®ç¾©ãåç
§ã®äº(ææã)ã
ãã®ãããªã³ã¼ãã®æ¸ãæ¹(Applicative ã¹ã¿ã¤ã«ã¨è¨ã)ã¯ãä¸è¨ã®æ³¨æç¹ãããã
- é£çµããå¼å ¨ã¦ãè©ä¾¡ããã
- å¼ã®è©ä¾¡çµæã次ã®å¼ã¸æ¸¡ããªã
ãããã®äºãã Validation ã¯ãæ£ã« Validation å¦çã«é©ãã¦ããã¨è¨ãã(w;
è足ã ããEither ã® Apply ã¯ãä¸è¨ã®éãã
//..snip.. trait Applys { def FunctorBindApply[Z[_]](implicit t: Functor[Z], b: Bind[Z]) = new Apply[Z] { def apply[A, B](f: Z[A => B], a: Z[A]): Z[B] = { lazy val fv = f lazy val fa = a b.bind(fv, (g: A => B) => t.fmap(fa, g(_: A))) } } } //..snip.. object Apply extends ApplyLow { //..snip.. implicit def EitherApply[X]: Apply[({type λ[α]=Either[X, α]})#λ] = FunctorBindApply[({type λ[α]=Either[X, α]})#λ] //..snip.. }
Either ã® fmap ã¯ä¸è¨ã®éãã
implicit def EitherFunctor[X]: Functor[({type λ[α]=Either[X, α]})#λ] = new Functor[({type λ[α]=Either[X, α]})#λ] { def fmap[A, B](r: Either[X, A], f: A => B) = r match { case Left(a) => Left(a) case Right(a) => Right(f(a)) } }
Either ã® bind ã¯ãä¸è¨ã®éãã
implicit def EitherBind[X]: Bind[({type λ[α]=Either[X, α]})#λ] = new Bind[({type λ[α]=Either[X, α]})#λ] { def bind[A, B](r: Either[X, A], f: A => Either[X, B]) = r.fold(Left(_), f) }
ã£ã¦äºã§(ä½ãï¼)ä¸è¨ã®éãã¨ãªã(ææã)ã
("foo".left[Int] <*> (1.right[String] <*> ("bar".left[Int] map ((_: Int) + (_: Int) + (_: Int)).curried))) assert_=== "bar".left[Int] (("foo".left[Int] |@| 1.right[String] |@| "bar".left[Int]) {_ + _ + _}) assert_=== "foo".left[Int]
for å¼ã§ä½¿ã£ãå ´åã¨ç°ãªããå·¦ããå³ã¸å ¨ã¦ã®å¼ãè©ä¾¡ãããå¾ã«ãçµæãã¾ã¨ããããã
è¨å·ã«ã¤ãã¦
scalaz ã§ã¯ã¡ã½ããåã«è¨å·ãç¨ãããã¦ããããã¯ã¦ã ã«æ稿ããéã« &#8728; ã®ããã«å¤æããã¦ãã¾ãäºãããããããã©ãã«ããªããªãããªï¼
ã©ãããã³ã¼ããè²¼ä»ããç®æã®ã¿ããããªãæ§å