few simple-type-tricks in scala

20
Scala: few simple type tricks for mortals Ruslan Shevchenko <[email protected]>

Upload: ruslan-shevchenko

Post on 15-Apr-2017

408 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Few simple-type-tricks in scala

Scala: few simple type tricks for mortals

Ruslan Shevchenko <[email protected]>

Page 2: Few simple-type-tricks in scala

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

scala types

Structured

Classical OO

Algebraic

Generic

Aliasing

5D SPACE

Page 4: Few simple-type-tricks in scala

Alternatives

• Classical OO / Algebraic (case classes)

• Generic / Type Alias

• Structured / Nominal

// decrease problem space

Page 5: Few simple-type-tricks in scala

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

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

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

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

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

{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

{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

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

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

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

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

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

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

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

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

Questions ?

• Thanks for attention.