Skip to content

Instantly share code, notes, and snippets.

@bvenners
Created January 3, 2014 17:17
Show Gist options
  • Select an option

  • Save bvenners/8242014 to your computer and use it in GitHub Desktop.

Select an option

Save bvenners/8242014 to your computer and use it in GitHub Desktop.
First attempt at an applicative instance for accumulating Ors
// 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