Last active
December 5, 2018 17:49
-
-
Save yeputons/97809890433da23387f57492b1a6e4f5 to your computer and use it in GitHub Desktop.
Scala examples on 05.12.2018
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
case class Context(canRead: Boolean) | |
val pages = Map( | |
1 -> "Hello", | |
2 -> "World" | |
) | |
def getPage(id: Int)(implicit context: Context): Option[String] = | |
if (context.canRead) | |
pages.get(id) | |
else | |
None | |
def getUrl(url: String)(implicit context: Context): Option[String] = { | |
val pageRegex = raw"/page/(\d+)".r | |
url match { | |
case pageRegex(id) => getPage(id.toInt) // syntax sugar for pageRegex.unapply(url) match { Some(List(id)) => ... } | |
case _ => None | |
} | |
} | |
{ | |
implicit val context1 = Context(canRead = false) | |
println(getPage(1)) // None | |
println(getUrl("/page/1")) // None | |
} | |
{ | |
implicit val context2 = Context(canRead = true) | |
println(getPage(2)) // Some("World") | |
println(getUrl("/page/2")) // Some("World") | |
println(getUrl("/foo")) // None | |
println(getUrl("/page/3")) // None | |
} |
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
trait MyEq[T] { // Haskell: class MyEq a where | |
def myEq(a: T, b: T): Boolean | |
} | |
def myImplicitly[T](implicit value: T): T = value | |
implicit class MyEqOps[T : MyEq](a: T) { //(implicit eq: MyEq[T]) { // Pimp my library | |
def =^^=(b: T): Boolean = myImplicitly[MyEq[T]].myEq(a, b) //eq.myEq(a, b) | |
} | |
def printIsEqual[T : MyEq](a: T, b: T) = //(implicit eq: MyEq[T]) = | |
println( | |
if (a =^^= b) "==" else "!=" | |
) | |
implicit object IntMyEq extends MyEq[Int] { // Haskell: instance MyEq Int where | |
def myEq(a: Int, b: Int) = Math.abs(a - b) <= 1 // Do not do that, it's not transitive. | |
} | |
// Haskell: instance MyEq a => MyEq [a] where | |
implicit def ListMyEq[T : MyEq] = new MyEq[List[T]] { | |
def myEq(a: List[T], b: List[T]) = | |
if (a.length == b.length) | |
a.zip(b).forall { case (x, y) => x =^^= y } // zipAll may be a better fit | |
else | |
false | |
} | |
printIsEqual(10, 10) | |
printIsEqual(10, 20) | |
printIsEqual(List(10, 20), List(10, 20)) | |
printIsEqual(List(10, 20), List(10, 20, 30)) | |
printIsEqual(List(10, 20), List(10, 30)) | |
printIsEqual(List(10, 20), List(11, 19)) |
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
sealed trait TypeEq[A, B] | |
implicit def createTypeEq[T]: TypeEq[T, T] = ??? | |
implicitly[TypeEq[Int, Int]] | |
implicit def foo[A, B](a: A, b: B)(implicit evidence: TypeEq[A, B]) = ??? | |
foo[Int, Int](1, 2) // compiles | |
foo[Int, String](1, "2") // compilation error | |
implicitly[TypeEq[Int, String]] |
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
class A(x: Int) { | |
case class B(v: Int) // Path-dependent types | |
def foo(): B = B(x) | |
def bar(x: A) = { | |
val y: A#B = x.foo() | |
} | |
} | |
val a1 = new A(1) | |
val a2 = new A(2) | |
//val x: a1.B = a2.foo() |
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 scala.language.higherKinds | |
trait NatFold[Up] { | |
type VO <: Up | |
type VS[_ <: Nat] <: Up | |
} | |
sealed trait Nat { | |
type Plus[B <: Nat] <: Nat | |
type IsZero[VO <: Up, VS <: Up, Up] <: Up | |
type MinusOne <: Nat | |
type Fold[_ <: NatFold[Up], Up] <: Up | |
//type Fold[VO <: Up, VS[_ <: Nat] <: Up, Up] <: Up | |
} | |
class O extends Nat { | |
type Plus[B <: Nat] = B | |
type IsZero[VO <: Up, VS <: Up, Up] = VO | |
type MinusOne = O | |
type Fold[F <: NatFold[Up], Up] = F#VO | |
//type Fold[VO <: Up, VS[_ <: Nat] <: Up, Up] = VO | |
} | |
class S[T <: Nat] extends Nat { | |
type Plus[B <: Nat] = S[T#Plus[B]] | |
type IsZero[VO <: Up, VS <: Up, Up] = VS | |
type MinusOne = T | |
type Fold[F <: NatFold[Up], Up] = F#VS[T] | |
//type Fold[VO <: Up, VS[_ <: Nat] <: Up, Up] = VS[T] | |
} | |
// illegal cyclic reference involving type Plus | |
// type Plus[A <: Nat, B <: Nat] = A#Fold[B, Plus[_, S[B]], Nat] | |
object Nat { | |
trait MultFold[B <: Nat] extends NatFold[Nat] { | |
type VO = O | |
type VS[T <: Nat] = B#Plus[T#Fold[MultFold[B], Nat] /*Mult[T, B]*/] | |
} | |
type Mult[A <: Nat, B <: Nat] = A#Fold[MultFold[B], Nat] | |
trait FacFold extends NatFold[Nat] { | |
type VO = S[O] | |
type VS[T <: Nat] = Mult[S[T], /*T#Fold[FacFold, Nat]*/ Fac[T]] | |
} | |
type Fac[A <: Nat] = A#Fold[FacFold, Nat] | |
} | |
type _1 = S[O] | |
type _2 = S[_1] | |
type _3 = S[_2] | |
type _4 = S[_3] | |
type _5 = S[_4] | |
class NatRep[T <: Nat](val i: Int) | |
implicit val repO = new NatRep[O](0) | |
implicit def repS[T <: Nat](implicit rep: NatRep[T]) = new NatRep[S[T]](rep.i + 1) | |
def toInt[T <: Nat](implicit rep: NatRep[T]) = rep.i | |
/* | |
println(toInt[_4#Plus[_3]]) | |
println(toInt[_4#IsZero[_1, _2, Nat]]) // 2 | |
println(toInt[O#IsZero[_1, _2, Nat]]) // 1 | |
println(toInt[_5#MinusOne]) // 4 | |
*/ | |
//println(toInt[Nat.Mult[_3, _5]]) | |
println(toInt[Nat.Fac[_3]]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment