Skip to content

Instantly share code, notes, and snippets.

@yeputons
Last active December 5, 2018 17:49
Show Gist options
  • Save yeputons/97809890433da23387f57492b1a6e4f5 to your computer and use it in GitHub Desktop.
Save yeputons/97809890433da23387f57492b1a6e4f5 to your computer and use it in GitHub Desktop.
Scala examples on 05.12.2018
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
}
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))
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]]
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()
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