Skip to content

Instantly share code, notes, and snippets.

View gszeliga's full-sized avatar

Guillermo Szeliga gszeliga

View GitHub Profile
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.NoSuchElementException;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public abstract class Either<L,R> {
object HipsterRules {
import com.covariantblabbering.builder.ApplicativeStyleWithMultipleMessages.SmartBuilderOps._
def facialHairStyle(hair: String) = {
if(hair.toLowerCase.contains("beard")) hair.success
else "You need to make vikings envious with any bushy or scraggly beard".failure
}
def tshirt(style: String) = {
object SmartBuilderOps
{
implicit val applicative = applicativeBuilder[String]
implicit def toSmartBuilderOps[E,A,B](s: BuildStep[E,A => B])=new SmartBuilderOps(s)
implicit def smartify[E,A,B,C](target: Curryable[A,B,C])(implicit applicative: Applicative[({type f[x] = BuildStep[E, x]})#f]) = toSmartBuilderOps(applicative.unit(target.curried))
implicit def toValidationOps[T](v: T) = new ValidationOps(v)
}
sealed trait BuildStep[+E, +A]{
def toEither: Either[E,A]
}
final case class Continue[A](v: A) extends BuildStep[Nothing,A] {
def toEither = Right(v)
}
final case class Failure[E](e: List[E]) extends BuildStep[List[E], Nothing] {
def toEither = Left(e)
}
object HipsterRules {
import com.covariantblabbering.builder.ApplicativeStyleWithExceptions._
def facialHairStyle(hair: String) = {
if(hair.toLowerCase.contains("beard")) Continue(hair)
else Failure(new Exception("You need to make vikings envious with any bushy or scraggly beard"))
}
def tshirt(style: String) = {
case class Hipster(facialHair: String, shirt: String, band: String, hobbie: String)
final class SmartBuilder[A,B](val f: BuildStep[Throwable,A => B])
{
def @> [E <: Throwable](step: BuildStep[E,A])(implicit applicative: Applicative[({type f[x] = BuildStep[Throwable, x]})#f]) = {
applicative.apply(f)(step)
}
}
object SmartBuilderOps
{
def <<= [A](f: BuildStep[Throwable, A]) = f match {
def applicativeBuilder[E] = new Applicative[({type f[x] = BuildStep[E, x]})#f] {
def unit[A](a: A) = Continue(a)
override def map2[A, B, C](fa: BuildStep[E, A], fb: BuildStep[E, B])(f: (A, B) => C) = {
(fa, fb) match{
case (Continue(a), Continue(b)) => Continue(f(a,b))
case (Failure(e1), Failure(e2)) => Failure(e1)
case (f @ Failure(_), _) => f
case (_, f @ Failure(_)) => f
trait Functor[F[_]]{
def map[A,B](fa: F[A])(f: A => B): F[B]
}
trait Applicative[F[_]] extends Functor[F]
{
def map2[A,B,C](fa: F[A], fb: F[B])(f: (A,B) => C): F[C] = {
apply(map(fa)(a => f(a,_:B)))(fb)
}
trait BuildStep[+E, +A]
case class Continue[T](v: T) extends BuildStep[Nothing, T]
case class Failure[E](e: E) extends BuildStep[E, Nothing]