Skip to content

Instantly share code, notes, and snippets.

@ferhtaydn
Last active June 28, 2017 17:23
Show Gist options
  • Save ferhtaydn/f152b2f4c59d27028f88557aa902b5aa to your computer and use it in GitHub Desktop.
Save ferhtaydn/f152b2f4c59d27028f88557aa902b5aa to your computer and use it in GitHub Desktop.
enum ListEnum[+A] {
case Cons[+A](h: A, t: ListEnum[A]) extends ListEnum[A]
case Empty extends ListEnum[Nothing]
}
val emptyList = ListEnum.Empty
// val res4: ListEnum[Nothing] = Empty
val list = ListEnum.Cons(1, ListEnum.Cons(2, ListEnum.Cons(3, ListEnum.Empty)))
// val res5: ListEnum[Int] = Cons(1,Cons(2,Cons(3,Empty)))
def sum(list: ListEnum[Int]): Int = list match {
case ListEnum.Empty => 0
case ListEnum.Cons(h, t) => h + sum(t)
}
println(sum(list))
// 6
// taken from: https://github.com/lampepfl/dotty/issues/1970
enum class Planet(mass: Double, radius: Double) {
private final val G = 6.67300E-11
def surfaceGravity = G * mass / (radius * radius)
def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity
}
object Planet {
case MERCURY extends Planet(3.303e+23, 2.4397e6)
case VENUS extends Planet(4.869e+24, 6.0518e6)
case EARTH extends Planet(5.976e+24, 6.37814e6)
case MARS extends Planet(6.421e+23, 3.3972e6)
case JUPITER extends Planet(1.9e+27, 7.1492e7)
case SATURN extends Planet(5.688e+26, 6.0268e7)
case URANUS extends Planet(8.686e+25, 2.5559e7)
case NEPTUNE extends Planet(1.024e+26, 2.4746e7)
}
def calculateEarthWeightOnPlanets(earthWeight: Double) = {
val mass = earthWeight/Planet.EARTH.surfaceGravity
for (p <- Planet.enumValues)
println(s"Your weight on $p is ${p.surfaceWeight(mass)}")
}
calculateEarthWeightOnPlanets(80)
/*
Your weight on MERCURY is 30.22060921607482
Your weight on SATURN is 85.28124310492532
Your weight on VENUS is 72.39992798728365
Your weight on URANUS is 72.41017595115402
Your weight on EARTH is 80.0
Your weight on NEPTUNE is 91.06624579757263
Your weight on MARS is 30.29897472297031
Your weight on JUPITER is 202.44460203965926
*/
package scala
import annotation.implicitNotFound
@implicitNotFound("Values of types ${L} and ${R} cannot be compared with == or !=")
sealed trait Eq[-L, -R]
object Eq extends Eq[Any, Any]
sealed trait StringParser[A] {
def parse(s: String): Try[A]
}
object StringParser {
def apply[A](implicit parser: StringParser[A]): StringParser[A] = parser
private def baseParser[A](f: String ⇒ Try[A]): StringParser[A] = new StringParser[A] {
override def parse(s: String): Try[A] = f(s)
}
implicit val stringParser: StringParser[String] = baseParser(Success(_))
implicit val intParser: StringParser[Int] = baseParser(s ⇒ Try(s.toInt))
implicit def optionParser[A](implicit parser: => StringParser[A]): StringParser[Option[A]] = new StringParser[Option[A]] {
override def parse(s: String): Try[Option[A]] = s match {
case "" ⇒ Success(None) // implicit parser not used.
case str ⇒ parser.parse(str).map(x ⇒ Some(x)) // implicit parser is evaluated at here
}
}
}
import StringParser._
println(implicitly[StringParser[Option[Int]]].parse("21"))
// Success(Some(21))
println(implicitly[StringParser[Option[Int]]].parse(""))
// Success(None) => implicit parser parameter is not evaluated at this call.
println(implicitly[StringParser[Option[Int]]].parse("21a"))
// Failure(java.lang.NumberFormatException: For input string: "21a")
def convert[T, U](x: T)(implicit converter: ImplicitConverter[T, U]): U = converter(x)
case class IntWrapper(a: Int) extends AnyVal
case class DoubleWrapper(b: Double) extends AnyVal
implicit val IntWrapperToDoubleWrapper = new ImplicitConverter[IntWrapper, DoubleWrapper] {
override def apply(i: IntWrapper): DoubleWrapper = new DoubleWrapper(i.a.toDouble)
}
// not working in dotty
//implicit val IntToDouble: IntWrapper => DoubleWrapper = int: IntWrapper => DoubleWrapper(int.a.toDouble)
convert(new IntWrapper(42))
// val res6: DoubleWrapper = DoubleWrapper(42.0)
// type alias Contextual
type Contextual[T] = implicit ExecutionContext => T
// sum is expanded to sum(x, y)(ctx)
def asyncSum(x: Int, y: Int): Contextual[Future[Int]] = Future(x + y)
// def asyncSum(x: Int, y: Int): Contextual[concurrent.Future[Int]]
def asyncMult(x: Int, y: Int) = { implicit ctx: ExecutionContext =>
Future(x * y)
}
// def asyncMult(x: Int, y: Int): implicit concurrent.ExecutionContext => scala.concurrent.Future[Int]
// then if you have implicit in scope, you can call your method as usual.
// compiler automatically convert them to curried implicit parameters as usual.
// def asyncMult(x: Int, y: Int)(implicit ec: ExecutionContext) = ???
import ExecutionContext.Implicits.global
asyncSum(3, 4).foreach(println)
// 7
asyncMult(3, 4).foreach(println)
// 12
trait ImplicitFuntion1[-T, +R] extends Function1[T, R] {
def apply(implicit t: T): R
}
import odersky.scaladays-cph-2017.talk._
import dotty-docs._
import dotty-example-project._
trait T(x: Int)
/ \
class C extends T(22) | trait U extends T
\ /
class D extends
C with U
sealed trait X {
def x: Double
def tpe: X
}
sealed trait Y {
def y: Double
def tpe: Y
}
// to show intersection types are also commutative
type P = Y & X
type PP = X & Y
final case class Point(x: Double, y: Double) extends X with Y {
override def tpe: X & Y = ???
}
def euclideanDistance(p1: X & Y, p2: X & Y) = {
Math.sqrt(Math.pow(p2.y - p1.y, 2) + Math.pow(p2.x - p1.x, 2))
}
val p1: P = Point(3, 4)
val p2: PP = Point(6, 8)
euclideanDistance(p1, p2)
// val res2: Double = 5.0
@volatile lazy val xs: List[String] = List("d", "o", "t", "t", "y")
import dotty.DottyPredef.{eqAny => _, _}
// if you don't define eqIntString, this line does not compile:
// Values of types Int and String cannot be compared with == or !=
implicit def eqIntString: Eq[Int, String] = Eq
println(3 == "3")
// false
// As default all Sequences are comparable, because of;
// implicit def eqSeq[T, U](implicit eq: Eq[T, U]): Eq[Seq[T], Seq[U]] = Eq
println(List(1, 2) == Vector(1, 2))
// true
class A(a: Int)
class B(b: Int)
val a = new A(4)
val b = new B(4)
implicit def eqAB: Eq[A, B] = Eq
println(a != b)
// true
implicit def eqBA: Eq[B, A] = Eq
println(b == a)
// false
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
implicit object listFunctor extends Functor[List] {
override def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
}
def fmap[F[_], A, B](fa: F[A])(f: A => B)(implicit F: Functor[F]): F[B] = F.map(fa)(f)
// here you can set type parameters when you are calling your parameterized functions.
val result: List[Int] = fmap[F = List, A = Int, B = Int](List(1,2,3))(i => i + 1)
// val result: List[Int] = List(2, 3, 4)
// val notCompileExample = fmap[F = List, B = String](List(1,2,3))(i => i + 1)
val compileExample: List[String] = fmap[F = List, B = String](List(1,2,3))(i => (i + 1).toString)
// val compile: List[String] = List(2, 3, 4)
val xs: List[String] = List("d", "o", "t", "t", "y")
// instead of
// xs.zipWithIndex.foreach { case (s, i) => println(s"$i: $s") }
xs.zipWithIndex.foreach((s, i) => println(s"$i: $s"))
// 0: d
// 1: o
// 2: t
// 3: t
// 4: y
T | U
/ \
T <: U
\ /
T & U
trait Base
class A extends { val msg = "Hello" } with Base {
def sayHi = msg
}
val a = new A
a.sayHi
// res3: String = Hello
trait Base(val msg: String)
class A extends Base("Hello")
class B extends Base("Dotty!")
def printMessages(msgs: (A | B)*) = println(msgs.map(_.msg).mkString(" "))
printMessages(new A, new B)
// Hello Dotty!
type T[+X, Y] = Map[Y, X]
type Tuple = [X] => (X, X)
val m: T[String, Int] = Map(1 -> "1")
val tuple: Tuple[String] = ("a", "b")
sealed trait Division
final case class DivisionByZero(msg: String) extends Division
final case class Success(double: Double) extends Division
// Create a type alias for your union types (sum types).
type DivisionResult = DivisionByZero | Success
sealed trait Either[+A, +B]
final case class Left[+A, +B](a: A) extends Either[A, B]
final case class Right[+A, +B](b: B) extends Either[A, B]
def safeDivide(a: Double, b: Double): DivisionResult = {
if (b == 0) DivisionByZero("DivisionByZeroException") else Success(a / b)
}
def either[A, B](division: Division) = division match {
case DivisionByZero(m: String) => Left(m)
case Success(d: Double) => Right(d)
}
val divisionResultSuccess: DivisionResult = safeDivide(4, 2)
// types are commutative: A | B == B | A
val divisionResultFailure: Success | DivisionByZero = safeDivide(4, 0)
either(divisionResultSuccess)
// val res0: Either[String, Double] & Product = Right(2.0)
either(divisionResultFailure)
// val res1: Either[String, Double] & Product = Left(DivisionByZeroException)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment