Created
January 3, 2014 17:17
-
-
Save bvenners/8242014 to your computer and use it in GitHub Desktop.
First attempt at an applicative instance for accumulating Ors
This file contains hidden or 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
| // Here's code that can be pasted into an interpreter sesssion: | |
| import scalaz._ | |
| import Scalaz._ | |
| import org.scalautils._ | |
| def all[F[_]: Applicative, A](s: String, parsers: List[String => F[A]]): F[List[A]] = parsers.traverse(p => p(s)) | |
| implicit class BadDog[G, B](or: Or[G, B]) { | |
| def badMap[C](bToC: B => C): G Or C = or.swap.map(bToC).swap | |
| } | |
| def toIntE(s: String): Int Or ErrorMessage = attempt(s.toInt).badMap(_.getMessage) | |
| def one: String => (Int Or List[ErrorMessage]) = s => toIntE(s).badMap(List(_)) | |
| def two: String => (Int Or List[ErrorMessage]) = s => toIntE(s.take(2)).badMap(List(_)) | |
| def three: String => (Int Or List[ErrorMessage]) = s => toIntE(s.drop(2)).badMap(List(_)) | |
| // all[({ type l[a] = a Or List[ErrorMessage] })#l, Int]("1234", List(one, two, three)) | |
| // all[({ type l[a] = a Or List[ErrorMessage] })#l, Int]("asfasf", List(one, two, three)) | |
| def oneA: String => (Int Or Every[ErrorMessage]) = s => toIntE(s).badMap(Every(_)) | |
| def twoA: String => (Int Or Every[ErrorMessage]) = s => toIntE(s.take(2)).badMap(Every(_)) | |
| def threeA: String => (Int Or Every[ErrorMessage]) = s => toIntE(s.drop(2)).badMap(Every(_)) | |
| implicit def accumulatingOrApplicative[G, B, E[b] <: Every[b]]: Applicative[({type l[g] = g Or Every[B]})#l] = | |
| new Applicative[({type l[g] = g Or Every[B]})#l] { | |
| override def map[G, H](fa: G Or Every[B])(f: G => H) = fa map f | |
| def point[G](g: => G) = Good(g) | |
| def ap[G, H](fa: => G Or Every[B])(f: => ((G => H) Or Every[B])): H Or Every[B] = | |
| (fa, f) match { | |
| case (Good(g), Good(f)) => Good(f(g)) | |
| case (Bad(b), Good(_)) => Bad(b) | |
| case (Good(f), Bad(b)) => Bad(b) | |
| case (Bad(b1), Bad(b2)) => Bad(b1 ++ b2) | |
| } | |
| } | |
| all[({ type l[a] = a Or Every[ErrorMessage] })#l, Int]("1234", List(oneA, twoA, threeA)) | |
| all[({ type l[a] = a Or Every[ErrorMessage] })#l, Int]("asfasf", List(oneA, twoA, threeA)) | |
| // Here's what it looks like when you do: | |
| scala> import scalaz._ | |
| import scalaz._ | |
| scala> import Scalaz._ | |
| import Scalaz._ | |
| scala> import org.scalautils._ | |
| import org.scalautils._ | |
| scala> def all[F[_]: Applicative, A](s: String, parsers: List[String => F[A]]): F[List[A]] = parsers.traverse(p => p(s)) | |
| warning: there were 1 feature warning(s); re-run with -feature for details | |
| all: [F[_], A](s: String, parsers: List[String => F[A]])(implicit evidence$1: scalaz.Applicative[F])F[List[A]] | |
| scala> implicit class BadDog[G, B](or: Or[G, B]) { | |
| | def badMap[C](bToC: B => C): G Or C = or.swap.map(bToC).swap | |
| | } | |
| defined class BadDog | |
| scala> def toIntE(s: String): Int Or ErrorMessage = attempt(s.toInt).badMap(_.getMessage) | |
| toIntE: (s: String)org.scalautils.Or[Int,org.scalautils.ErrorMessage] | |
| scala> def one: String => (Int Or List[ErrorMessage]) = s => toIntE(s).badMap(List(_)) | |
| one: String => org.scalautils.Or[Int,List[org.scalautils.ErrorMessage]] | |
| scala> def two: String => (Int Or List[ErrorMessage]) = s => toIntE(s.take(2)).badMap(List(_)) | |
| two: String => org.scalautils.Or[Int,List[org.scalautils.ErrorMessage]] | |
| scala> def three: String => (Int Or List[ErrorMessage]) = s => toIntE(s.drop(2)).badMap(List(_)) | |
| three: String => org.scalautils.Or[Int,List[org.scalautils.ErrorMessage]] | |
| scala> // all[({ type l[a] = a Or List[ErrorMessage] })#l, Int]("1234", List(one, two, three)) | |
| scala> // all[({ type l[a] = a Or List[ErrorMessage] })#l, Int]("asfasf", List(one, two, three)) | |
| scala> def oneA: String => (Int Or Every[ErrorMessage]) = s => toIntE(s).badMap(Every(_)) | |
| oneA: String => org.scalautils.Or[Int,org.scalautils.Every[org.scalautils.ErrorMessage]] | |
| scala> def twoA: String => (Int Or Every[ErrorMessage]) = s => toIntE(s.take(2)).badMap(Every(_)) | |
| twoA: String => org.scalautils.Or[Int,org.scalautils.Every[org.scalautils.ErrorMessage]] | |
| scala> def threeA: String => (Int Or Every[ErrorMessage]) = s => toIntE(s.drop(2)).badMap(Every(_)) | |
| threeA: String => org.scalautils.Or[Int,org.scalautils.Every[org.scalautils.ErrorMessage]] | |
| scala> implicit def accumulatingOrApplicative[G, B, E[b] <: Every[b]]: Applicative[({type l[g] = g Or Every[B]})#l] = | |
| | new Applicative[({type l[g] = g Or Every[B]})#l] { | |
| | override def map[G, H](fa: G Or Every[B])(f: G => H) = fa map f | |
| | | |
| | def point[G](g: => G) = Good(g) | |
| | | |
| | def ap[G, H](fa: => G Or Every[B])(f: => ((G => H) Or Every[B])): H Or Every[B] = | |
| | (fa, f) match { | |
| | case (Good(g), Good(f)) => Good(f(g)) | |
| | case (Bad(b), Good(_)) => Bad(b) | |
| | case (Good(f), Bad(b)) => Bad(b) | |
| | case (Bad(b1), Bad(b2)) => Bad(b1 ++ b2) | |
| | } | |
| | } | |
| warning: there were 1 feature warning(s); re-run with -feature for details | |
| accumulatingOrApplicative: [G, B, E[b] <: org.scalautils.Every[b]]=> scalaz.Applicative[[g]org.scalautils.Or[g,org.scalautils.Every[B]]] | |
| scala> all[({ type l[a] = a Or Every[ErrorMessage] })#l, Int]("1234", List(oneA, twoA, threeA)) | |
| res22: org.scalautils.Or[List[Int],org.scalautils.Every[String]] = Good(List(1234, 12, 34)) | |
| scala> all[({ type l[a] = a Or Every[ErrorMessage] })#l, Int]("asfasf", List(oneA, twoA, threeA)) | |
| res23: org.scalautils.Or[List[Int],org.scalautils.Every[String]] = Bad(Many(For input string: "fasf", For input string: "as", For input string: "asfasf")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment