20
Motivation and Mechanics behind some aspects of Shapeless

Motivation and Mechanics behind some aspects of Shapeless

Embed Size (px)

Citation preview

Page 1: Motivation and Mechanics behind some aspects of Shapeless

Motivation and Mechanics behind some aspects of

Shapeless

Page 2: Motivation and Mechanics behind some aspects of Shapeless

Plan

•Motivation•HList•Coproduct•Generic•Example

Page 3: Motivation and Mechanics behind some aspects of Shapeless

Motivation

Page 4: Motivation and Mechanics behind some aspects of Shapeless

Theory: product, coproduct and type classes

• Product: a and b.

• Coproduct: a or b.

• Type class: operations possible on a type.

type Phone = (Manufacturer, Model, Imei)

sealed trait Device

trait Phone extends Device

trait Laptop extends Device

trait ShowCsv[A] {

def showCsv(a: A): String

}

Page 5: Motivation and Mechanics behind some aspects of Shapeless

Why Shapeless?

•Manipulation of the Scala data types (e.g. treat a case class as a list).

•Type-level representations of data structures and operations over them.

Page 6: Motivation and Mechanics behind some aspects of Shapeless

HList: Generalisation of the product type

Page 7: Motivation and Mechanics behind some aspects of Shapeless

HList: Implementation

sealed trait HList

case class ::[+H, +T <: HList](head : H, tail : T) extends HList

case object HNil extends HList

Page 8: Motivation and Mechanics behind some aspects of Shapeless

HList: Example – Head of an Empty Listscala> List(1).head

res0: Int = 1

scala> Nil.head

java.util.NoSuchElementException: head of empty list

at scala.collection.immutable.Nil$.head(List.scala:420)

... 42 elided

scala> (1 :: HNil).head

res2: Int = 1

scala> HNil.head

<console>:15: error: could not find implicit value for parameter

c: shapeless.ops.hlist.IsHCons[shapeless.HNil.type]

HNil.head

Page 9: Motivation and Mechanics behind some aspects of Shapeless

Coproduct

Page 10: Motivation and Mechanics behind some aspects of Shapeless

Coproduct: Implementation

trait Coproduct

trait :+:[+H, +T <: Coproduct] extends

case class Inl[+H, +T <: Coproduct](head : H) extends :+:[H, T]

case class Inr[+H, +T <: Coproduct](tail : T) extends :+:[H, T]

trait CNil extends Coproduct

Page 11: Motivation and Mechanics behind some aspects of Shapeless

Shapeless Operations

Page 12: Motivation and Mechanics behind some aspects of Shapeless

Shapeless Operations

•Data types (HList, Coproduct etc) reside under the shapeless package.•Operations on these data types are provided by type

classes under shapeless.ops package.•Syntax available via rich wrappers under the shapeless.syntax package.•Companion objects of data types provide implicit

conversions to the rich wrappers.•Rich wrappers delegate to operation type classes.

Page 13: Motivation and Mechanics behind some aspects of Shapeless

Shapeless Operations: HList companion

object HList {

import syntax.HListOps

implicit def hlistOps[L <: HList](l: L): HListOps[L] = new HListOps(l)

}

Page 14: Motivation and Mechanics behind some aspects of Shapeless

Shapeless Operations: HList Syntax

final class HListOps[L <: HList](l : L) {

def head(implicit c: IsHCons[L]): c.H = c.head(l)

def tail(implicit c: IsHCons[L]): c.T = c.tail(l

}

Page 15: Motivation and Mechanics behind some aspects of Shapeless

Shapeless Operations: HList Type classes

object hlist {

trait IsHCons[L <: HList] {

type H

type T <: HList

def head(l: L): H

def tail(l: L): T

def cons(h: H, t: T): L

}

object IsHCons { /*...*/ }

}

Page 16: Motivation and Mechanics behind some aspects of Shapeless

Generic

Page 17: Motivation and Mechanics behind some aspects of Shapeless

Generic – Motivation

•HLists and Coproducts are another way to express case classes and supertypes.•They provide lost of useful collections operations.•Can we apply these operations to case classes or

supertypes?•Can we define operations applicable to all case

classes or supertypes? E.g. convert any case class to CSV string without defining the logic for each case class?

Page 18: Motivation and Mechanics behind some aspects of Shapeless

Generic: Implementationtrait Generic[T] {

type Repr

def to(t : T) : Repr

def from(r : Repr) : T

}

object Generic {

type Aux[T, Repr0] = Generic[T] { type Repr = Repr0 }

def apply[T](implicit gen: Generic[T]): Aux[T, gen.Repr] = gen

implicit def materialize[T, R]: Aux[T, R] =

macro GenericMacros.materialize[T, R]

}

Page 19: Motivation and Mechanics behind some aspects of Shapeless

Live Example: Converting an electronic store’s database to

CSV

Page 20: Motivation and Mechanics behind some aspects of Shapeless

Q&A