few simple-type-tricks in scala
TRANSCRIPT
![Page 2: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/2.jpg)
Hieronymus Bosch “A visual guide to the Scala language” oil on oak panels, 1490-1510
// http://classicprogrammerpaintings.tumblr.com/
![Page 3: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/3.jpg)
scala types
Structured
Classical OO
Algebraic
Generic
Aliasing
5D SPACE
![Page 4: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/4.jpg)
Alternatives
• Classical OO / Algebraic (case classes)
• Generic / Type Alias
• Structured / Nominal
// decrease problem space
![Page 5: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/5.jpg)
Alternatives• Prefer specific style
• (typelevel: prefer Generic + ADT)
• (java++ : prefer OO + std. ADT)
• Try to set some rules.
• http://www.lihaoyi.com/post/StrategicScalaStylePrincipleofLeastPower.html
• least power
• most readability
![Page 6: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/6.jpg)
Alternatives• Classical OO / ADT
• state vs functionality.OO: Object = State + Function
FP: State = ADT, passive. Object = Service over State
Non-ADT Object with state ? rare, special, ….
![Page 7: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/7.jpg)
Alternatives• Generic/Type Alias
case class User[IdType,Address]( id: IdType, firstName: String. lastName: String address: Address )
case class User extends IdEntity( id: IdType, firstName: String, lastName: String, address: Address ) { type Address = ….. )
![Page 8: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/8.jpg)
Type Aliases are path-dependedval a = retrieveUser(“a1”) val b = retrieveUser(“b1”)
a.address and b.address - different types
Aux patternobject User { type Aux[I,A] = User { type IdType = I type Address = A } }
def method[Id,Type](user: User.Aux[Id,Type] ): X = …………..
// original from shapeless
![Page 9: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/9.jpg)
When to prefer generic ?• Containers.
• Compositions.
• Internal machinery.
• (part of more complex process)
• Dotty: unification of type aliases and type parameters.
![Page 10: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/10.jpg)
{compile/run}-time dispatch• run time dispatch — via java virtual dispatch
• depends from one object
• final object type can not be known at compile-time
• compile time dispatch — via implicit resolution
• depends from multiple objects
• final object types must be known at compile-time
![Page 11: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/11.jpg)
{compile/run}-time dispatch• run time dispatch — via java virtual dispatch
• depends from one object
• final object type can not be known at compile-time
• compile time dispatch — via implicit resolution
• depends from multiple objects
• final object types must be known at compile-time
Immutable data —> we know constructor
![Page 12: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/12.jpg)
implicit resolution• provide global rule in you world
• rule must be really global or special for you types
• good citizent in big project must be tolerant:
• do not force others to know something about you implicits
• keep you implicits in your scope [companion obj, etc]
• problem: we want to have different behaviour for different object state (known at compile time)
![Page 13: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/13.jpg)
tagged typesobject tagged types { trait Tagged[+V] type @@[V,T] = V with Tagged[T]
implicit class WithTag[V](val v:V) extends AnyVal { def @@[T](t:T) = v.asInstanceOf[T] def tag[T] = v.asInstanceOf[T] } }
// origin: was as scalaz, shapeless
![Page 14: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/14.jpg)
tagged typesobject tagged types { trait Tagged[+V] type @@[V,T] = V with Tagged[T]
implicit class WithTag[V](val v:V) extends AnyVal { def @@[T](t:T) = v.asInstanceOf[T] def tag[T] = v.asInstanceOf[T] } }
// origin: was as scalaz, shapeless
sealed trait UserLifecycle trait New extends UserLifecycle trait Existing extends UserLifecycle
case class User(….)
![Page 15: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/15.jpg)
tagged typesobject tagged types { trait Tagged[+V] type @@[V,T] = V with Tagged[T]
implicit class WithTag[V](val v:V) extends AnyVal { def @@[T](t:T) = v.asInstanceOf[T] def tag[T] = v.asInstanceOf[T] } }
// origin: was as scalaz, shapeless
case class Msg(v:String)
object User { implicit def msgNew(u: User @@New:Msg = Msg(“Hi”) implicit def msgExisting(u: User@@Existing):Msg = Msg(“Hi again!”) }
sealed trait UserLifecycle trait New extends UserLifecycle trait Existing extends UserLifecycle
![Page 16: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/16.jpg)
tagged typesobject tagged types { trait Tagged[+V] type @@[V,T] = V with Tagged[T]
implicit class WithTag[V](val v:V) extends AnyVal { def @@[T](t:T) = v.asInstanceOf[T] def tag[T] = v.asInstanceOf[T] } }
// see: refinement
case class Msg(v:String)
object User { implicit def msgNew(u: User @@New:Msg = Msg(“Hi”) implicit def msgExisting(u: User@@Existing):Msg = Msg(“Hi again!”) }
sealed trait UserLifecycle trait New extends UserLifecycle trait Existing extends UserLifecycle
class UserService { def create(cn: Info): User @@ New def meet(u: User @@ New): User @@ Existing }
val u = userService.create(cn) printMsg(u) > >> “Hi”
val u1 = userService.meet(u) printMsg(u1) >>> “Hi again!”
![Page 17: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/17.jpg)
implicit evidence• existing implicit evidence <=> existence of
property
object example { def notCallMeWithA[T](t:T)(implicit evidence: Not[A,T])
trait Not[A,T] implicit def n1[A,B](implicit evidence A <:< B) = Not.instance implicit def n2[A,B](implicit evidence B <:< A) = Not.instance implicit def n3[A] = Not.instance }
![Page 18: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/18.jpg)
type arithmeticstrait Nat { type Current <: Nat type Next <: Nat }
type Zero { type Current = Zero type Next = Succ(Zero) }
type Succ[X<:Nat] { type Current = Succ[X] type Next = Succ[Succ[X]] }
type _0 = Zero type _1 = Succ[Zero] type _2 = Succ[Succ[Zero]]
totally ineffective shapeless contains effective implementation
class SizedList[X <: Nat] { …… }
![Page 19: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/19.jpg)
Resources:• shapeless (big, use with care)
• https://github.com/milessabin/shapeless
• http://mpilquist.github.io/blog/2015/04/22/intro-to-shapeless/
• type-level computations
• http://slick.typesafe.com/talks/scalaio2014/Type-Level_Computations.pdf
![Page 20: Few simple-type-tricks in scala](https://reader031.vdocument.in/reader031/viewer/2022030316/587757161a28ab84388b78db/html5/thumbnails/20.jpg)
Questions ?
• Thanks for attention.