Last active
March 7, 2019 22:34
-
-
Save dwijnand/7dacd40dbbe1aa467b12eaf7fa985cb5 to your computer and use it in GitHub Desktop.
Rust's From/Into ported to Conversion.scala
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
-sbt-version | |
1.2.7 |
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
//sbt.version=1.2.7 | |
val frominto = project in file(".") | |
scalaVersion := "2.12.8" | |
addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.9.6") |
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
package frominto | |
// Rust's From and Into in Scala | |
/** Simple, safe and pure conversion from `A` into `B`. */ | |
trait Conversion[-A, +B] { | |
def convert(value: A): B | |
} | |
object Conversion { | |
implicit def refl[A]: Conversion[A, A] = x => x | |
implicit def optionConvert[A]: Conversion[A, Option[A]] = x => Option(x) | |
implicit class Syntax[A](private val value: A) extends AnyVal { | |
def convert[B](implicit c: Conversion[A, B]): B = c.convert(value) | |
} | |
} | |
object Main { | |
import Conversion.Syntax | |
def foo2[I, D, S](lorem: String, ipsum: I, dolor: D, sit: S)(implicit | |
I: Conversion[I, Option[Int]], | |
D: Conversion[D, Option[Int]], | |
S: Conversion[S, Option[Int]], | |
) = { | |
val ipsum2 = ipsum.convert getOrElse 0 | |
val dolor2 = dolor.convert getOrElse 0 | |
val sit2 = sit.convert getOrElse 0 | |
println(s"$ipsum2 $lorem $dolor2 $sit2") | |
} | |
def setReadTimeout3[A: Conversion[?, Option[Int]]](timeout: A) = { | |
timeout.convert match { | |
case Some(x) => println(s"set timeout to $x") | |
case None => println(s"unset timeout") | |
} | |
} | |
def main(args: Array[String]): Unit = { | |
foo2("bar", None, None, None) | |
foo2("bar", 42, None, None) | |
foo2("bar", 42, 1337, None) | |
foo2("bar", 42, 1337, -1) | |
setReadTimeout3(10) | |
setReadTimeout3(None) | |
} | |
type Marshaller[A] | |
type StatusCode | |
type HttpResponse | |
import scala.concurrent.Future | |
/** WARNING, side effecting, changes the world */ | |
sealed trait CompletionMagnet { | |
type Result | |
def finish(): Result | |
} | |
object CompletionMagnet { | |
implicit def fromStatusObject[T: Marshaller](tuple: (StatusCode, T)) = | |
new CompletionMagnet { | |
type Result = Unit | |
def finish(): Result = ??? // implementation using (StatusCode, T) tuple | |
} | |
implicit def fromHttpResponseFuture(future: Future[HttpResponse]) = | |
new CompletionMagnet { | |
type Result = Int | |
def finish(): Result = ??? // implementation using future | |
} | |
implicit def fromStatusCodeFuture(future: Future[StatusCode]) = | |
new CompletionMagnet { | |
type Result = Int | |
def finish(): Result = ??? // implementation using future | |
} | |
} | |
def complete[M, N <: CompletionMagnet](magnet: M)(implicit M: Conversion[M, N]): N#Result = | |
magnet.convert.finish() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment