Last active
February 1, 2017 04:22
-
-
Save hisui/42c63818284fdab5338365a1f5c0d46c to your computer and use it in GitHub Desktop.
This file contains 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
scalaVersion := "2.11.8" | |
resolvers ++= Seq( | |
Resolver.sonatypeRepo("releases"), | |
Resolver.sonatypeRepo("snapshots") | |
) | |
libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.2" |
This file contains 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
object Main extends App { | |
val a = Seq("a", "b", "c") | |
// syntax #1 | |
{ | |
import MyCoproductSyntax1._ | |
for (username <- a; password <- a) { | |
UserService.authenticate(username, password).foldTo[Unit] | |
.caseOf[Authenticated] (_ => println("You just logged in!")) | |
.caseOf[UserNotFound] (_ => println("Who are you?")) | |
.caseOf[UserBanned] (_ => println("Go back home.")) | |
.caseOf[BadCredential] (_ => println("Don't hack me.")) | |
.end | |
} | |
} | |
// syntax #2 | |
{ | |
import MyCoproductSyntax2._ | |
for (username <- a; password <- a) { | |
UserService.authenticate(username, password) foldWith ( | |
(_: Authenticated ) => println("You just logged in!"), | |
(_: UserNotFound ) => println("Who are you?"), | |
(_: UserBanned ) => println("Go back home."), | |
(_: BadCredential ) => println("Don't hack me.") | |
) | |
} | |
} | |
} |
This file contains 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
import shapeless.Coproduct | |
import shapeless.ops.coproduct.Remove | |
object MyCoproductSyntax1 { | |
implicit class CoproductOps[C <: Coproduct](val raw: C) extends AnyVal { | |
def foldTo[U] = new CoproductFold[U, C](Right(raw)) | |
} | |
class CoproductFold[U, C <: Coproduct](val raw: Either[U, C]) extends AnyVal { | |
def caseOf[H](f: H => U)(implicit rm: Remove[C, H]): CoproductFold[U, rm.Rest] = | |
raw.fold( | |
e => new CoproductFold(Left(e)), | |
e => new CoproductFold(rm(e).left map f) | |
) | |
def end(implicit ev: C =:= CNil): U = raw.left.get | |
} | |
} |
This file contains 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
import shapeless.HList | |
import shapeless.HNil | |
import shapeless.`::` | |
import shapeless.CNil | |
import shapeless.Coproduct | |
import shapeless.Generic | |
import shapeless.ops.coproduct.Remove | |
object MyCoproductSyntax2 { | |
trait ZipFold[C <: Coproduct, L <: HList, Z] { | |
type Out >: Z | |
def apply(c: C, list: L): Out | |
} | |
object ZipFold { | |
implicit def case_1[A1, A2 >: A1, H, T <: HList, C1 <: Coproduct, C2 <: Coproduct] | |
(implicit rm: Remove.Aux[C1, H, C2], next: ZipFold[C2, T, A2]) = new ZipFold[C1, (H => A2) :: T, A1] { | |
type Out = next.Out | |
def apply(c: C1, list: (H => A2) :: T): Out = rm(c).fold(list.head, next(_, list.tail)) | |
} | |
implicit def case_0[A] = new ZipFold[CNil, HNil, A] { | |
type Out = A | |
def apply(c: CNil, list: HNil): Out = throw new IllegalStateException("..bug? (*_*;)") | |
} | |
} | |
implicit class CoproductOps[C <: Coproduct](val raw: C) extends AnyVal { | |
def foldWith[U, P <: Product, L <: HList](cases: P) | |
(implicit gen: Generic.Aux[P, L], zip: ZipFold[C, L, Nothing]) = zip(raw, gen.to(cases)) | |
} | |
} |
This file contains 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
import shapeless.Coproduct | |
import shapeless.CNil | |
import shapeless.:+: | |
case class Authenticated() | |
case class BadCredential() | |
case class UserNotFound() | |
case class UserBanned() | |
object UserService { | |
type AuthenticateResult = | |
( Authenticated | |
:+: BadCredential | |
:+: UserNotFound | |
:+: UserBanned | |
:+: CNil | |
) | |
def authenticate(username: String, password: String): AuthenticateResult = | |
(username, password) match { | |
case ("a", "a") => Coproduct[AuthenticateResult](Authenticated()) | |
case ("a", _) => Coproduct[AuthenticateResult](BadCredential()) | |
case ("b", _) => Coproduct[AuthenticateResult](UserBanned()) | |
case (_ , _) => Coproduct[AuthenticateResult](UserNotFound()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment