SlideShare a Scribd company logo
Type Level Programming in scala
@liam.m
1
Requirements
— Scala? .
— !
— !
— !
— !
2
?
!
—
—
—
—
—
—
—
3
?
4
Once your code compiles it usually works.2
.
2 
https://wiki.haskell.org/Why_Haskell_just_works
5
TDD
TDD - Type driven development3
3 
https://www.manning.com/books/type-driven-development-with-idris
6
1. Type safe equality - ===
2. Builder pattern using Phantom type
3. Type class pattern - implicit
4. Literal type - 42.type
5. Dependent type - a.B
Type .
7
Equality?
val items = List(
Item(1, Some("ON_SALE")), Item(2, Some("SOLDOUT")),
Item(3, Some("ON_SALE")), Item(4, None))
items.filter(item => item.status == "ON_SALE")
?
8
Equality?
val items = List(
Item(1, Some("ON_SALE")), Item(2, Some("SOLDOUT")),
Item(3, Some("ON_SALE")), Item(4, None))
items.filter(item => item.status == "ON_SALE")
Nil .
item.status: Option[String] != "ON_SALE": String
9
.
!
test("item status filter") {
val expected = List(
Item(1, Some("ON_SALE")),
Item(3, Some("ON_SALE"))
)
assert(items == expected) // !
}
10
.
!
test("item status filter") {
val expected = List(
Item(1, Some("ON_SALE")),
Item(3, Some("ON_SALE"))
)
assert(items == expected) // !
}
?
11
.
!
test("item status filter") {
val expected = List(
Item(1, Some("ON_SALE")),
Item(3, Some("ON_SALE"))
)
assert(items == expected) // !
}
?
Once your code compiles it usually works.
12
Type safe equality
implicit class StrictEq[A](a: A) {
def ===(b: A) = a == b
}
13
Type safe equality
implicit class StrictEq[A](a: A) {
def ===(b: A) = a == b
}
implicit class .
A ===
14
COMPILE TIME .
val x = Some("ON_SALE")
val y = Some("SOLDOUT")
val z = "ON_SALE"
x === y // false
x === z // doesn't compile,
.
⛑
15
=== .
...
16
scalacOptions += "-Xfatal-warnings"
case class UserId(n: Int)
val john = UserId(7)
john == 7
// <console>:11: warning: comparing values of
// types UserId and Int using `=='
// will always yield false john == 7
warning -> error
17
18
19
Builder pa!ern
"The builder pattern is a good choice when designing
classes whose constructors or static factories would
have more than a handful of parameters."
Joshua Bloch, Effective Java
!
20
Builder pa!ern
"The builder pattern is a good choice when designing
classes whose constructors or static factories would
have more than a handful of parameters."
Joshua Bloch, Effective Java
!
21
// , .
public class Item {
private Integer id;
private Integer brandId;
private Integer catalogId;
private Integer supplyChannelId; // optional
private String supplyChannelItemCode;
private String supplyChannelCategoryCode;
private String name;
private String displayName;
private Integer itemType;
private Integer basicPrice;
private Integer sellingPrice;
private Integer discountRate;
private Integer feeRate;
private Byte periodType;
private Integer validPeriod;
private Byte pinIssueType;
private String pinIssueCsInfo; // optional
private Boolean isCancelable;
private String imageUrl; // optional
private Integer status;
private Boolean displayYn;
private Short distType; // optional
private String detailInfo; // optional
private String noticeInfo; // optional
private Instant couponExpiredAt; // optional
private Instant releasedAt;
private Instant expiredAt;
... // 51
}
?
22
- Joshua Bloch
public class Item {
public static class Builder {
// Builder
public Builder(Integer id, Integer brandId, Integer catalogId, String supplyChannelItemCode,
String supplyChannelCategoryCode, String name, String displayName, Integer itemType,
Integer basicPrice, Integer sellingPrice, Integer discountRate, Integer feeRate,
Byte periodType, Integer validPeriod, String pinIssueCsInfo, Byte pinIssueType,
Boolean isCancelable, Integer status, Boolean displayYn, Instant releasedAt, Instant expiredAt) {
this.id = id; this.brandId = brandId; this.catalogId = catalogId;
this.supplyChannelItemCode = supplyChannelItemCode;
this.supplyChannelCategoryCode = supplyChannelCategoryCode;
this.name = name; this.displayName = displayName; this.itemType = itemType;
this.basicPrice = basicPrice; this.sellingPrice = sellingPrice;
this.discountRate = discountRate; this.feeRate = feeRate;
this.periodType = periodType; this.validPeriod = validPeriod;
this.pinIssueType = pinIssueType; this.pinIssueCsInfo = pinIssueCsInfo;
this.isCancelable = isCancelable; this.status = status;
this.displayYn = displayYn; this.releasedAt = releasedAt; this.expiredAt = expiredAt;
}
//
public Builder withSupplyChannelId(Integer val) {
this.supplyChannelId = val;
return this;
}
public Builder withPinIssueCsInfo(String val) {
this.pinIssueCsInfo = val;
return this;
}
...
}
}
23
Builder builder .
Item item = new Item.Builder(
10,
1000,
2000,
"I123",
"C123",
"( ) ",
" ",
101,
5000,
3000,
40,
5,
(byte)2,
365,
"CS",
(byte) 3,
true,
201,
true,
Instant.now(),
Instant.MAX
).withNoticeInfo(" ").withImageUrl("http://builder.jpg")
.build();
24
: Builder builder
— Builder withXXX
25
/* Item.scala */
case class Item(
id: Int,
brandId: Int,
catalogId: Int,
supplyChannelId: Option[Int], //
supplyChannelItemCode: String, // .
supplyChannelCategoryCode: String,
name: String,
displayName: String,
itemType: Int,
basicPrice: Int,
sellingPrice: Int,
discountRate: Int,
feeRate: Int,
periodType: Byte,
validPeriod: Int,
pinIssueType: Byte,
pinIssueCsInfo: Option[String],
isCancelable: Boolean,
imageUrl: Option[String],
status: Int,
displayYn: Boolean,
distType: Option[Short],
detailInfo: Option[String],
noticeInfo: Option[String],
couponExpiredAt: Option[Instant],
releasedAt: Instant,
expiredAt: Instant
)
26
type .
27
type .
Why?
28
type .
Why? Compiler type type
29
type .
Why? Compiler type type
// .
sealed trait BuildState {
type Id <: Bool // True
type Name <: Bool // True
}
30
sealed trait Bool
val True = new Bool {}
val False = new Bool {}
val hasOption: Bool = True
31
sealed trait Bool
sealed trait True extends Bool
sealed trait False extends Bool
type HasOption = True
32
— ADT Values : val → trait
val True = new Bool {} ➜ trait True extends Bool
33
— ADT Values : val → trait
val True = new Bool {} ➜ trait True extends Bool
— members : val → type X
val hasOption: Bool = True ➜ type HasOption = True
34
sealed trait Bool
//
val True = new Bool {}
val False = new Bool {}
val hasOption: Bool = True
//
sealed trait True extends Bool
sealed trait False extends Bool
type HasOption = True
35
Name, DisplayName True
class Builder[B <: BuildState] { self =>
private var name: Option[String] = None
private var displayName: Option[String] = None
def newBuilder[C <: BuildState] = this.asInstanceOf[Builder[C]]
def withName(name: String) = {
self.name = Some(name)
newBuilder[B {type Name = True}]
}
def withDisplayName(displayName: String) = {
self.displayName = Some(displayName)
newBuilder[B {type DisplayName = True}]
}
}
36
True
class Builder[B <: BuildState] { self =>
def build(implicit
ev1: B#Id =:= True, // True
ev2: B#BrandId =:= True,
ev3: B#CatalogId =:= True,
ev4: B#SupplyChannelItemCode =:= True,
ev5: B#SupplyChannelCategoryCode =:= True,
ev6: B#Name =:= True,
ev7: B#DisplayName =:= True,
ev8: B#ItemType =:= True,
ev9: B#BasicPrice =:= True,
ev10: B#SellingPrice =:= True,
ev11: B#DiscountRate =:= True,
ev12: B#FeeRate =:= True,
...
): Item =
Item(id.get, brandId.get, catalogId.get, supplyChannelId, supplyChannelItemCode.get,
supplyChannelCategoryCode.get, name.get, displayName.get, itemType.get, basicPrice.get,
sellingPrice.get, discountRate.get, feeRate.get, periodType.get, validPeriod.get,
pinIssueType.get, pinIssueCsInfo, isCancelable.get, imageUrl, status.get, displayYn.get,
distType, detailInfo, noticeInfo, couponExpiredAt, releasedAt.get, expiredAt.get)
}
37
BuildState .
class Builder[B <: BuildState] { self =>
private var name: Option[String] = None
private var detailInfo: Option[String] = None // optional
def withName(name: String) = { //
self.name = Some(name)
newBuilder[B {type Name = True}]
}
def withDetailInfo(detailInfo: String) = { //
self.detailInfo = Some(detailInfo)
newBuilder[B]
}
}
38
39
object Builder {
def apply() = new Builder[BuildState {}]
}
//
Builder().build // doesn't compile, .
Builder()
.withBasicPrice(5000).build // doesn't compile, .
40
// . withXXX . .
val item = Builder()
.withId(10)
.withBrandId(1000)
.withCatalogId(2000)
.withSupplyChannelItemCode("I123")
.withSupplyChannelCategoryCode("C123")
.withName("( ) ")
.withDisplayName(" ")
.withItemType(101)
.withBasicPrice(5000)
.withSellingPrice(3000)
.withDiscountRate(40)
.withFeeRate(5)
.withPeriodType(2)
.withValidPeriod(365)
.withPinIssueType(3)
.withIsCancelable(true)
.withStatus(201)
.withDisplayYn(true)
.withReleasedAt(now)
.withExpiredAt(Instant.MAX)
.build
41
// named argument ... ? ?
val item = Item(
id = 10, brandId = 1000, catalogId = 2000,
supplyChannelId = None, supplyChannelItemCode = "I123",
supplyChannelCategoryCode = "C123", name = "( ) ",
displayName = " ", itemType = 101,
basicPrice = 5000, sellingPrice = 3000,
discountRate = 40, feeRate = 5,
periodType = 2, validPeriod = 365,
pinIssueType = 3, pinIssueCsInfo = None,
isCancelable = true, imageUrl = None,
status = 201, displayYn = true,
distType = None, detailInfo = None,
noticeInfo = None, couponExpiredAt = None,
releasedAt = now, expiredAt = Instant.MAX
)
42
?
43
?
?
44
Type class Pa!ern
sum .
case class Point(x: Int, y: Int) // 2
sum(List(1, 2, 3)) => 6
sum(List(Point(1,10), Point(5, 5)) => Point(6, 15)
45
trait Adder[A] {
def zero: A
def add(x: A, y: A): A
}
46
trait Adder[A] {
def zero: A
def add(x: A, y: A): A
}
def sum[A](xs: List[A])(adder: Adder[A]): A =
xs.foldLeft(adder.zero)(adder.add)
47
val intAdder = new Adder[Int] {
def zero: Int = 0
def add(x: Int, y: Int) = x + y
}
val pointAdder = new Adder[Point] {
def zero = Point(0, 0)
def add(a: Point, b: Point) = Point(a.x + b.x, a.y + b.y)
}
48
.
sum(List(1, 2, 3))(intAdder) // 7
sum(List(Point(1, 10), Point(5, 5)))(pointAdder) // Point(6, 15)
49
. .
sum(List(1, 2, 3))(intAdder) // <= .
sum(List(Point(1, 10), Point(5, 5)))(pointAdder) // <=
50
Type class pa!ern ?
def sum[A](xs: List[A])(implicit adder: Adder[A]): A
Ad-hoc polymorphism - type parameter
implicit instance polymorphism
DI - compiler dependency injection
Spring, Guice runtime DI
51
implicit
!
// Adder implicit
def sum[A](xs: List[A])(implicit adder: Adder[A]): A =
xs.foldLeft(adder.zero)(adder.add)
// type class instance implicit
implicit val intAdder = new Adder[Int] {
def zero = 0
def add(x: Int, y: Int) = x + y
}
implicit val pointAdder = new Adder[Point] {
def zero = Point(0, 0)
def add(a: Point, b: Point) = Point(a.x + b.x, a.y + b.y)
}
52
sum(List(1, 2, 3))(intAdder)
sum(List(Point(1, 10), Point(5, 5)))(pointAdder)
53
sum(List(1, 2, 3))
sum(List(Point(1, 10), Point(5, 5)))
54
sum(List(1, 2, 3))
sum(List(Point(1, 10), Point(5, 5)))
// String compile .
sum(List("Hello", "World")) // doesn't compile
//
!
55
String ?
// string instance .
implicit val stringAdder = new Adder[String] {
def zero = ""
def add(x: String, y: String) = x + y
}
sum(List("Hello", "World")) // => "HelloWorld"
56
. .
...
.
.
. .
57
58
Literal type - 42.type
?
59
Literal type - 42.type
? .
!
val t: 42 = 42
val x: "Jedi" = "Jedi"
60
Literal type - 42.type
? .
!
val t: 42 = 42
val x: "Jedi" = "Jedi"
?
61
Literal type - 42.type
? .
!
val t: 42 = 42
val x: "Jedi" = "Jedi"
? .
!
def f(t: Double): t.type = t
val a: 1.2 = f(1.2)
62
Literal type in scala
Scala http://docs.scala-lang.org/sips/pending/42.type.html
Typelevel Scala https://typelevel.org/scala/
Dotty http://dotty.epfl.ch/docs/reference/singleton-types.html
.
Literal singleton type library
.
63
true.type if condition
trait Cond[T] { type V ; val value: V }
implicit val condTrue = new Cond[true] { type V = String ; val value = "foo" }
implicit val condFalse = new Cond[false] { type V = Int ; val value = 23 }
def cond[T](implicit cond: Cond[T]): cond.V = cond.value
// true is type!
!
cond[true] // "foo"
// flase is type!
"
cond[false] // 23
64
Path Dependent type -
class A {
class B
var b: Option[B] = None
}
65
Path Dependent type -
class A {
class B
var b: Option[B] = None
}
val a1: A = new A
val a2: A = new A
val b1: a1.B = new a1.B // a1.B .
val b2: a2.B = new a2.B // a1.B a2.B .
b1 === b2 //
66
Path Dependent type -
val b1: a1.B = new a1.B // a1.B .
val b2: a2.B = new a2.B // a1.B a2.B .
a1.b = Some(b1)
a2.b = Some(b1) // does not compile
Dependent Type Programming
67
Map - .
val strIntMap: Map[String, Int] = Map("width" -> 120)
68
Map - .
val strIntMap: Map[String, Int] = Map("width" -> 120)
Sting Map Value ?
69
Map - .
val strIntMap: Map[String, Int] = Map("width" -> 120)
Sting Map Value ? Any
val strAnyMap: Map[String, Any] = strIntMap + ("sort" -> "time")
70
Map - .
val strIntMap: Map[String, Int] = Map("width" -> 120)
Sting Map Value ? Any
val strAnyMap: Map[String, Any] = strIntMap + ("sort" -> "time")
// ?
val width: Option[Any] = map2.get("width")
val sort: Option[Any] = map2.get("sort")
71
HMap - Heterogenous Map1
Dependent type !
1 
Dotty : https://www.slideshare.net/Odersky/from-dot-to-dotty
72
HMap - Heterogenous Map1
Dependent type !
trait Key { type Value }
trait HMap {
def get(key: Key): Option[key.Value] // key Value, dependent type!
def add(key: Key)(value: key.Value): HMap
}
1 
Dotty : https://www.slideshare.net/Odersky/from-dot-to-dotty
73
val sort = new Key { type Value = String }
val width = new Key { type Value = Int }
74
val sort = new Key { type Value = String }
val width = new Key { type Value = Int }
Key Value
val hmap: HMap = HMap.empty
.add(width)(120)
.add(sort)("time")
.add(width)(true) // doesn't compile, width Int Value .
75
val sort = new Key { type Value = String }
val width = new Key { type Value = Int }
Key Value
val hmap: HMap = HMap.empty
.add(width)(120)
.add(sort)("time")
.add(width)(true) // doesn't compile, width Int Value .
Value .
val optionInt: Option[Int] = hmap.get(width)
val optionString: Option[String] = hmap.get(sort)
76
HMap ?
Martin Ordersky .
77
HMap ! 9
trait HMap { self =>
val underlying: Map[Any, Any]
def get(key: Key): Option[key.Value] =
underlying.get(key).map(_.asInstanceOf[key.Value])
def add(key: Key)(value: key.Value): HMap =
new HMap {
val underlying = self.underlying + (key -> value)
}
}
78
Believing that: Life is Study!4
4 
https://twitter.com/ktosopl
79
NilOnce your code compiles it usually works.
80
Back up Slide
?
81
Back up Slide
?
?
82
Back up Slide
?
?
?
83
Back up Slide
?
?
?
84
Scala in Real World.
Parallel Programming in Micro Service Architecture.5
5 
http://tech.kakao.com/2017/09/02/parallel-programming-and-applicative-in-scala/
85
86
.
SELECT *
FROM
items, catalogs, wishes, categories, details, certificiations
WHERE
items.id = ?
AND items.id = catalogs.itemId
AND items.id = wishes.itemId
...
87
.
val product: Future[ProductDto] = for {
item <- itemReposotory.findByid(itemId) //
catalog <- catalogRepository.findById(item.catalogId) //
brand <- brandRepository.findById(item.brandId) //
wish <- itemWishCountRepository.findByItemId(item.id) //
category <- categoryRepository.findOneByBrandId(item.brandId) //
detail <- itemDetailRepository.findByItemId(item.id) //
cert <- itemCertificationRepository.findByItemId(item.id) //
} yield ProductFactory.of(item, brand, catalog, wish, category, detail, cert)
88
?
89
.
90
!!!
!
91
?
Applicative .
92
Applicative?
93
Applicative -
94
Applicative -
trait Applicative[F[_]] {
def pure[A](a: A): F[A]
def ap[A, B](fa: F[A])(ff: F[A => B]): F[B]
}
95
Applicative - ap
import scala.concurrent.Future
val futureAp = new Applicative[Future] {
def pure[A](a: A) = Future.successful(a)
def ap[A, B](fa: Future[A])(ff: Future[A => B]): Future[B] =
ff.zip(fa).map { case (f, a) => f(a)}
}
96
Applicative can be parallel
itemRepository.findById(itemId).flatMap { item =>
(
catalogRepository.findById(item.catalogId) |@|
brandRepository.findById(item.brandId) |@|
itemWishCountRepository.findByItemId(item.id) |@|
categoryRepository.findOneByBrandId(item.brandId) |@|
itemDetailRepository.findByItemId(item.id) |@|
itemCertificationRepository.findByItemId(item.id)
).map { case (catalog, brand, wish, category, detail, cert) =>
List(brand, catalog, wish, category, detail, cert)
}
}
97
98
99
Backgroud - Phantom type
!
Phantom( ) type Compile time
Runtime
trait Phantom //
type MyInt = Int with Phantom // Phantom type mixin
100
Int has no meaning
A Int can contains anything
Int 42 9496 7296 .
101
def findItemsBy(brandId: Int, itemId: Int,
status: Int, page: Int, size: Int = 20) =
items.filter(_.brandId == brandId).drop(page * size).take(size)
// ItemService.scala
// .
findItemsByBrandId(brandId, itemId, status, page, size)
102
?
// catalogId , Id
def findItemsBy(brandId: Int, itemId: Int,catalogId: Int,
status: Int, page: Int, size: Int = 20) =
items.filter(_.brandId == brandId).drop(page * size).take(size)
// BrandService.scala
// API .
findItemsByBrandId(brandId, itemId, catalogId, status, page, size)
103
?
// catalogId , Id
def findItemsBy(brandId: Int, itemId: Int,catalogId: Int,
status: Int, page: Int, size: Int = 20) =
items.filter(_.brandId == brandId).drop(page * size).take(size)
// BrandService.scala
// API .
findItemsByBrandId(brandId, itemId, catalogId, status, page, size)
// ItemService.scala
// ?
findItemsByBrandId(brandId, itemId, status, page, size)
104
.
?
105
User defined type
Compiler .
case class ItemId(value: Int) extends AnyVal
case class CatalogId(value: Int) extends AnyVal
case class BrandId(value: Int) extends AnyVal
case class Status(value: Int) extends AnyVal
case class Page(value: Int) extends AnyVal
case class Size(value: Int) extends AnyVal
106
API
def findItemsByBrandId(
brandId: BrandId, itemId: ItemId, catalogId: CatalogId,
status: Status, page: Page, size: Size = Size(20)
): List[Item] =
items.filter(_.brandId == brandId.value)
.drop(page.value * size.value)
.take(size.value)
findItemsByBrandId(brandId, itemId, status, page, size) // doesn't compile,
107
? .
!
// before
def findItemsBy(
brandId: Int, itemId: Int,catalogId: Int,
status: Int, page: Int, size: Int = 20): List[Item] =
items
.filter(_.brandId == brandId)
.drop(page * size)
.take(size)
// after
def findItemsByBrandId(
brandId: BrandId, itemId: ItemId, catalogId: CatalogId,
status: Status, page: Page, size: Size = Size(20)): List[Item] =
items.filter(_.brandId == brandId.value)
.drop(page.value * size.value) //
.take(size.value) //
?
!
?
"
108
Page type
Int Int .
case class Page(value: Int) extends AnyVal
Page Int ? Page extends Int
Page Int .
val page: Int = Page(1) // .
109
shapeless .
import shapeless._
val shapely =
"Dependent type programming"
:: "Generic type programming" :: HNil
https://github.com/milessabin/shapeless
.
110
Tagged type
!
Phantom( ) type Compile time ( )
TypeTag @@ Phantom type
import shapeless.tag.@@
type Page = Int @@ PageTag // Page Int PageTag
val page: Page = tag[PageTag][Int](1) // ,
111
Tagged type
!
Phantom( ) type Compile time
TypeTag @@ Phantom type
import shapeless.tag.@@
type Page = Int @@ PageTag // Page Int PageTag
val page: Page = tag[PageTag][Int](1) // ,
// PageTag Int
page.getClass // => class java.lang.Integer
// Int .
val int : Int = page
112
Phantom type
— .
— (final) .
— API .
— .
113
import shapeless.tag.@@
trait BrandIdTag; trait ItemIdTag
trait BrandTag; trait ItemTag
trait PageTag; trait SizeTag
object Pagable {
type Page = Int @@ PageTag // Page Int
type Size = Int @@ SizeTag // Size Int
}
def findItemsByBrandId(brandId: Int, page: Page, size: Size): List[Item] =
items.filter(_.brandId == brandId)
.drop(page * size) // Page => Int !
.take(size) //
val page: Page = tag[PageTag][Int](1)
val size: Size = tag[SizeTag][Int](20)
findItemsByBrandId(1, page, size) // works
// page size .
findItemsByBrandId(1, size, page) // doesn't compile
114

More Related Content

What's hot

Swift as an OOP Language
Swift as an OOP LanguageSwift as an OOP Language
Swift as an OOP Language
Ahmed Ali
 
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
James Titcumb
 
Java script basics
Java script basicsJava script basics
Java script basics
Shrivardhan Limbkar
 
ECMA5 approach to building JavaScript frameworks with Anzor Bashkhaz
ECMA5 approach to building JavaScript frameworks with Anzor BashkhazECMA5 approach to building JavaScript frameworks with Anzor Bashkhaz
ECMA5 approach to building JavaScript frameworks with Anzor Bashkhaz
FITC
 
Practical Object-Oriented Back-in-Time Debugging
Practical Object-Oriented Back-in-Time DebuggingPractical Object-Oriented Back-in-Time Debugging
Practical Object-Oriented Back-in-Time Debugginglienhard
 
JavaScript symbols
JavaScript symbolsJavaScript symbols
JavaScript symbols
Ideas2IT Technologies
 
Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
Bernhard Schussek
 
Building Reusable Custom Elements With Angular
Building Reusable Custom Elements With AngularBuilding Reusable Custom Elements With Angular
Building Reusable Custom Elements With Angular
Ilia Idakiev
 
Sketchmine: Design Systems Tooling
Sketchmine: Design Systems ToolingSketchmine: Design Systems Tooling
Sketchmine: Design Systems Tooling
Stefan Baumgartner
 
Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to ask
Andrea Giuliano
 

What's hot (10)

Swift as an OOP Language
Swift as an OOP LanguageSwift as an OOP Language
Swift as an OOP Language
 
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
 
Java script basics
Java script basicsJava script basics
Java script basics
 
ECMA5 approach to building JavaScript frameworks with Anzor Bashkhaz
ECMA5 approach to building JavaScript frameworks with Anzor BashkhazECMA5 approach to building JavaScript frameworks with Anzor Bashkhaz
ECMA5 approach to building JavaScript frameworks with Anzor Bashkhaz
 
Practical Object-Oriented Back-in-Time Debugging
Practical Object-Oriented Back-in-Time DebuggingPractical Object-Oriented Back-in-Time Debugging
Practical Object-Oriented Back-in-Time Debugging
 
JavaScript symbols
JavaScript symbolsJavaScript symbols
JavaScript symbols
 
Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
 
Building Reusable Custom Elements With Angular
Building Reusable Custom Elements With AngularBuilding Reusable Custom Elements With Angular
Building Reusable Custom Elements With Angular
 
Sketchmine: Design Systems Tooling
Sketchmine: Design Systems ToolingSketchmine: Design Systems Tooling
Sketchmine: Design Systems Tooling
 
Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to ask
 

Similar to Type level programming in Scala

ADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developers
Bartosz Kosarzycki
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java Developers
Yakov Fain
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
Sergio Ronchi
 
2 kotlin vs. java: what java has that kotlin does not
2  kotlin vs. java: what java has that kotlin does not2  kotlin vs. java: what java has that kotlin does not
2 kotlin vs. java: what java has that kotlin does not
Sergey Bandysik
 
CONSTRUCTORS IN C++ +2 COMPUTER SCIENCE
CONSTRUCTORS IN C++ +2 COMPUTER SCIENCECONSTRUCTORS IN C++ +2 COMPUTER SCIENCE
CONSTRUCTORS IN C++ +2 COMPUTER SCIENCE
Venugopalavarma Raja
 
Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013
Guillaume Laforge
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin
XPeppers
 
Kotlin for Android devs
Kotlin for Android devsKotlin for Android devs
Kotlin for Android devs
Adit Lal
 
14. Java defining classes
14. Java defining classes14. Java defining classes
14. Java defining classes
Intro C# Book
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
Pascal-Louis Perez
 
Intro to object oriented programming
Intro to object oriented programmingIntro to object oriented programming
Intro to object oriented programmingDavid Giard
 
Writing browser extensions_in_kotlin
Writing browser extensions_in_kotlinWriting browser extensions_in_kotlin
Writing browser extensions_in_kotlin
xavazque2
 
CSharp presentation and software developement
CSharp presentation and software developementCSharp presentation and software developement
CSharp presentation and software developement
frwebhelp
 
14. Defining Classes
14. Defining Classes14. Defining Classes
14. Defining Classes
Intro C# Book
 
R. herves. clean code (theme)2
R. herves. clean code (theme)2R. herves. clean code (theme)2
R. herves. clean code (theme)2
saber tabatabaee
 
Oop2010 Scala Presentation Stal
Oop2010 Scala Presentation StalOop2010 Scala Presentation Stal
Oop2010 Scala Presentation Stal
Michael Stal
 
XAML/C# to HTML/JS
XAML/C# to HTML/JSXAML/C# to HTML/JS
XAML/C# to HTML/JS
Michael Haberman
 
[OOP - Lec 13,14,15] Constructors / Destructor and its Types
[OOP - Lec 13,14,15] Constructors / Destructor and its Types[OOP - Lec 13,14,15] Constructors / Destructor and its Types
[OOP - Lec 13,14,15] Constructors / Destructor and its Types
Muhammad Hammad Waseem
 
03 oo with-c-sharp
03 oo with-c-sharp03 oo with-c-sharp
03 oo with-c-sharpNaved khan
 

Similar to Type level programming in Scala (20)

ADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developers
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java Developers
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
2 kotlin vs. java: what java has that kotlin does not
2  kotlin vs. java: what java has that kotlin does not2  kotlin vs. java: what java has that kotlin does not
2 kotlin vs. java: what java has that kotlin does not
 
CONSTRUCTORS IN C++ +2 COMPUTER SCIENCE
CONSTRUCTORS IN C++ +2 COMPUTER SCIENCECONSTRUCTORS IN C++ +2 COMPUTER SCIENCE
CONSTRUCTORS IN C++ +2 COMPUTER SCIENCE
 
Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin
 
Kotlin for Android devs
Kotlin for Android devsKotlin for Android devs
Kotlin for Android devs
 
14. Java defining classes
14. Java defining classes14. Java defining classes
14. Java defining classes
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
Intro to object oriented programming
Intro to object oriented programmingIntro to object oriented programming
Intro to object oriented programming
 
Writing browser extensions_in_kotlin
Writing browser extensions_in_kotlinWriting browser extensions_in_kotlin
Writing browser extensions_in_kotlin
 
CSharp presentation and software developement
CSharp presentation and software developementCSharp presentation and software developement
CSharp presentation and software developement
 
14. Defining Classes
14. Defining Classes14. Defining Classes
14. Defining Classes
 
Java 2
Java   2Java   2
Java 2
 
R. herves. clean code (theme)2
R. herves. clean code (theme)2R. herves. clean code (theme)2
R. herves. clean code (theme)2
 
Oop2010 Scala Presentation Stal
Oop2010 Scala Presentation StalOop2010 Scala Presentation Stal
Oop2010 Scala Presentation Stal
 
XAML/C# to HTML/JS
XAML/C# to HTML/JSXAML/C# to HTML/JS
XAML/C# to HTML/JS
 
[OOP - Lec 13,14,15] Constructors / Destructor and its Types
[OOP - Lec 13,14,15] Constructors / Destructor and its Types[OOP - Lec 13,14,15] Constructors / Destructor and its Types
[OOP - Lec 13,14,15] Constructors / Destructor and its Types
 
03 oo with-c-sharp
03 oo with-c-sharp03 oo with-c-sharp
03 oo with-c-sharp
 

Recently uploaded

How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Shahin Sheidaei
 
Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
e20449
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Yara Milbes
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
ShamsuddeenMuhammadA
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
takuyayamamoto1800
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 

Recently uploaded (20)

How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 
Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 

Type level programming in Scala

  • 1. Type Level Programming in scala @liam.m 1
  • 2. Requirements — Scala? . — ! — ! — ! — ! 2
  • 4. ? 4
  • 5. Once your code compiles it usually works.2 . 2  https://wiki.haskell.org/Why_Haskell_just_works 5
  • 6. TDD TDD - Type driven development3 3  https://www.manning.com/books/type-driven-development-with-idris 6
  • 7. 1. Type safe equality - === 2. Builder pattern using Phantom type 3. Type class pattern - implicit 4. Literal type - 42.type 5. Dependent type - a.B Type . 7
  • 8. Equality? val items = List( Item(1, Some("ON_SALE")), Item(2, Some("SOLDOUT")), Item(3, Some("ON_SALE")), Item(4, None)) items.filter(item => item.status == "ON_SALE") ? 8
  • 9. Equality? val items = List( Item(1, Some("ON_SALE")), Item(2, Some("SOLDOUT")), Item(3, Some("ON_SALE")), Item(4, None)) items.filter(item => item.status == "ON_SALE") Nil . item.status: Option[String] != "ON_SALE": String 9
  • 10. . ! test("item status filter") { val expected = List( Item(1, Some("ON_SALE")), Item(3, Some("ON_SALE")) ) assert(items == expected) // ! } 10
  • 11. . ! test("item status filter") { val expected = List( Item(1, Some("ON_SALE")), Item(3, Some("ON_SALE")) ) assert(items == expected) // ! } ? 11
  • 12. . ! test("item status filter") { val expected = List( Item(1, Some("ON_SALE")), Item(3, Some("ON_SALE")) ) assert(items == expected) // ! } ? Once your code compiles it usually works. 12
  • 13. Type safe equality implicit class StrictEq[A](a: A) { def ===(b: A) = a == b } 13
  • 14. Type safe equality implicit class StrictEq[A](a: A) { def ===(b: A) = a == b } implicit class . A === 14
  • 15. COMPILE TIME . val x = Some("ON_SALE") val y = Some("SOLDOUT") val z = "ON_SALE" x === y // false x === z // doesn't compile, . ⛑ 15
  • 17. scalacOptions += "-Xfatal-warnings" case class UserId(n: Int) val john = UserId(7) john == 7 // <console>:11: warning: comparing values of // types UserId and Int using `==' // will always yield false john == 7 warning -> error 17
  • 18. 18
  • 19. 19
  • 20. Builder pa!ern "The builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters." Joshua Bloch, Effective Java ! 20
  • 21. Builder pa!ern "The builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters." Joshua Bloch, Effective Java ! 21
  • 22. // , . public class Item { private Integer id; private Integer brandId; private Integer catalogId; private Integer supplyChannelId; // optional private String supplyChannelItemCode; private String supplyChannelCategoryCode; private String name; private String displayName; private Integer itemType; private Integer basicPrice; private Integer sellingPrice; private Integer discountRate; private Integer feeRate; private Byte periodType; private Integer validPeriod; private Byte pinIssueType; private String pinIssueCsInfo; // optional private Boolean isCancelable; private String imageUrl; // optional private Integer status; private Boolean displayYn; private Short distType; // optional private String detailInfo; // optional private String noticeInfo; // optional private Instant couponExpiredAt; // optional private Instant releasedAt; private Instant expiredAt; ... // 51 } ? 22
  • 23. - Joshua Bloch public class Item { public static class Builder { // Builder public Builder(Integer id, Integer brandId, Integer catalogId, String supplyChannelItemCode, String supplyChannelCategoryCode, String name, String displayName, Integer itemType, Integer basicPrice, Integer sellingPrice, Integer discountRate, Integer feeRate, Byte periodType, Integer validPeriod, String pinIssueCsInfo, Byte pinIssueType, Boolean isCancelable, Integer status, Boolean displayYn, Instant releasedAt, Instant expiredAt) { this.id = id; this.brandId = brandId; this.catalogId = catalogId; this.supplyChannelItemCode = supplyChannelItemCode; this.supplyChannelCategoryCode = supplyChannelCategoryCode; this.name = name; this.displayName = displayName; this.itemType = itemType; this.basicPrice = basicPrice; this.sellingPrice = sellingPrice; this.discountRate = discountRate; this.feeRate = feeRate; this.periodType = periodType; this.validPeriod = validPeriod; this.pinIssueType = pinIssueType; this.pinIssueCsInfo = pinIssueCsInfo; this.isCancelable = isCancelable; this.status = status; this.displayYn = displayYn; this.releasedAt = releasedAt; this.expiredAt = expiredAt; } // public Builder withSupplyChannelId(Integer val) { this.supplyChannelId = val; return this; } public Builder withPinIssueCsInfo(String val) { this.pinIssueCsInfo = val; return this; } ... } } 23
  • 24. Builder builder . Item item = new Item.Builder( 10, 1000, 2000, "I123", "C123", "( ) ", " ", 101, 5000, 3000, 40, 5, (byte)2, 365, "CS", (byte) 3, true, 201, true, Instant.now(), Instant.MAX ).withNoticeInfo(" ").withImageUrl("http://builder.jpg") .build(); 24
  • 25. : Builder builder — Builder withXXX 25
  • 26. /* Item.scala */ case class Item( id: Int, brandId: Int, catalogId: Int, supplyChannelId: Option[Int], // supplyChannelItemCode: String, // . supplyChannelCategoryCode: String, name: String, displayName: String, itemType: Int, basicPrice: Int, sellingPrice: Int, discountRate: Int, feeRate: Int, periodType: Byte, validPeriod: Int, pinIssueType: Byte, pinIssueCsInfo: Option[String], isCancelable: Boolean, imageUrl: Option[String], status: Int, displayYn: Boolean, distType: Option[Short], detailInfo: Option[String], noticeInfo: Option[String], couponExpiredAt: Option[Instant], releasedAt: Instant, expiredAt: Instant ) 26
  • 29. type . Why? Compiler type type 29
  • 30. type . Why? Compiler type type // . sealed trait BuildState { type Id <: Bool // True type Name <: Bool // True } 30
  • 31. sealed trait Bool val True = new Bool {} val False = new Bool {} val hasOption: Bool = True 31
  • 32. sealed trait Bool sealed trait True extends Bool sealed trait False extends Bool type HasOption = True 32
  • 33. — ADT Values : val → trait val True = new Bool {} ➜ trait True extends Bool 33
  • 34. — ADT Values : val → trait val True = new Bool {} ➜ trait True extends Bool — members : val → type X val hasOption: Bool = True ➜ type HasOption = True 34
  • 35. sealed trait Bool // val True = new Bool {} val False = new Bool {} val hasOption: Bool = True // sealed trait True extends Bool sealed trait False extends Bool type HasOption = True 35
  • 36. Name, DisplayName True class Builder[B <: BuildState] { self => private var name: Option[String] = None private var displayName: Option[String] = None def newBuilder[C <: BuildState] = this.asInstanceOf[Builder[C]] def withName(name: String) = { self.name = Some(name) newBuilder[B {type Name = True}] } def withDisplayName(displayName: String) = { self.displayName = Some(displayName) newBuilder[B {type DisplayName = True}] } } 36
  • 37. True class Builder[B <: BuildState] { self => def build(implicit ev1: B#Id =:= True, // True ev2: B#BrandId =:= True, ev3: B#CatalogId =:= True, ev4: B#SupplyChannelItemCode =:= True, ev5: B#SupplyChannelCategoryCode =:= True, ev6: B#Name =:= True, ev7: B#DisplayName =:= True, ev8: B#ItemType =:= True, ev9: B#BasicPrice =:= True, ev10: B#SellingPrice =:= True, ev11: B#DiscountRate =:= True, ev12: B#FeeRate =:= True, ... ): Item = Item(id.get, brandId.get, catalogId.get, supplyChannelId, supplyChannelItemCode.get, supplyChannelCategoryCode.get, name.get, displayName.get, itemType.get, basicPrice.get, sellingPrice.get, discountRate.get, feeRate.get, periodType.get, validPeriod.get, pinIssueType.get, pinIssueCsInfo, isCancelable.get, imageUrl, status.get, displayYn.get, distType, detailInfo, noticeInfo, couponExpiredAt, releasedAt.get, expiredAt.get) } 37
  • 38. BuildState . class Builder[B <: BuildState] { self => private var name: Option[String] = None private var detailInfo: Option[String] = None // optional def withName(name: String) = { // self.name = Some(name) newBuilder[B {type Name = True}] } def withDetailInfo(detailInfo: String) = { // self.detailInfo = Some(detailInfo) newBuilder[B] } } 38
  • 39. 39
  • 40. object Builder { def apply() = new Builder[BuildState {}] } // Builder().build // doesn't compile, . Builder() .withBasicPrice(5000).build // doesn't compile, . 40
  • 41. // . withXXX . . val item = Builder() .withId(10) .withBrandId(1000) .withCatalogId(2000) .withSupplyChannelItemCode("I123") .withSupplyChannelCategoryCode("C123") .withName("( ) ") .withDisplayName(" ") .withItemType(101) .withBasicPrice(5000) .withSellingPrice(3000) .withDiscountRate(40) .withFeeRate(5) .withPeriodType(2) .withValidPeriod(365) .withPinIssueType(3) .withIsCancelable(true) .withStatus(201) .withDisplayYn(true) .withReleasedAt(now) .withExpiredAt(Instant.MAX) .build 41
  • 42. // named argument ... ? ? val item = Item( id = 10, brandId = 1000, catalogId = 2000, supplyChannelId = None, supplyChannelItemCode = "I123", supplyChannelCategoryCode = "C123", name = "( ) ", displayName = " ", itemType = 101, basicPrice = 5000, sellingPrice = 3000, discountRate = 40, feeRate = 5, periodType = 2, validPeriod = 365, pinIssueType = 3, pinIssueCsInfo = None, isCancelable = true, imageUrl = None, status = 201, displayYn = true, distType = None, detailInfo = None, noticeInfo = None, couponExpiredAt = None, releasedAt = now, expiredAt = Instant.MAX ) 42
  • 43. ? 43
  • 45. Type class Pa!ern sum . case class Point(x: Int, y: Int) // 2 sum(List(1, 2, 3)) => 6 sum(List(Point(1,10), Point(5, 5)) => Point(6, 15) 45
  • 46. trait Adder[A] { def zero: A def add(x: A, y: A): A } 46
  • 47. trait Adder[A] { def zero: A def add(x: A, y: A): A } def sum[A](xs: List[A])(adder: Adder[A]): A = xs.foldLeft(adder.zero)(adder.add) 47
  • 48. val intAdder = new Adder[Int] { def zero: Int = 0 def add(x: Int, y: Int) = x + y } val pointAdder = new Adder[Point] { def zero = Point(0, 0) def add(a: Point, b: Point) = Point(a.x + b.x, a.y + b.y) } 48
  • 49. . sum(List(1, 2, 3))(intAdder) // 7 sum(List(Point(1, 10), Point(5, 5)))(pointAdder) // Point(6, 15) 49
  • 50. . . sum(List(1, 2, 3))(intAdder) // <= . sum(List(Point(1, 10), Point(5, 5)))(pointAdder) // <= 50
  • 51. Type class pa!ern ? def sum[A](xs: List[A])(implicit adder: Adder[A]): A Ad-hoc polymorphism - type parameter implicit instance polymorphism DI - compiler dependency injection Spring, Guice runtime DI 51
  • 52. implicit ! // Adder implicit def sum[A](xs: List[A])(implicit adder: Adder[A]): A = xs.foldLeft(adder.zero)(adder.add) // type class instance implicit implicit val intAdder = new Adder[Int] { def zero = 0 def add(x: Int, y: Int) = x + y } implicit val pointAdder = new Adder[Point] { def zero = Point(0, 0) def add(a: Point, b: Point) = Point(a.x + b.x, a.y + b.y) } 52
  • 53. sum(List(1, 2, 3))(intAdder) sum(List(Point(1, 10), Point(5, 5)))(pointAdder) 53
  • 54. sum(List(1, 2, 3)) sum(List(Point(1, 10), Point(5, 5))) 54
  • 55. sum(List(1, 2, 3)) sum(List(Point(1, 10), Point(5, 5))) // String compile . sum(List("Hello", "World")) // doesn't compile // ! 55
  • 56. String ? // string instance . implicit val stringAdder = new Adder[String] { def zero = "" def add(x: String, y: String) = x + y } sum(List("Hello", "World")) // => "HelloWorld" 56
  • 58. 58
  • 59. Literal type - 42.type ? 59
  • 60. Literal type - 42.type ? . ! val t: 42 = 42 val x: "Jedi" = "Jedi" 60
  • 61. Literal type - 42.type ? . ! val t: 42 = 42 val x: "Jedi" = "Jedi" ? 61
  • 62. Literal type - 42.type ? . ! val t: 42 = 42 val x: "Jedi" = "Jedi" ? . ! def f(t: Double): t.type = t val a: 1.2 = f(1.2) 62
  • 63. Literal type in scala Scala http://docs.scala-lang.org/sips/pending/42.type.html Typelevel Scala https://typelevel.org/scala/ Dotty http://dotty.epfl.ch/docs/reference/singleton-types.html . Literal singleton type library . 63
  • 64. true.type if condition trait Cond[T] { type V ; val value: V } implicit val condTrue = new Cond[true] { type V = String ; val value = "foo" } implicit val condFalse = new Cond[false] { type V = Int ; val value = 23 } def cond[T](implicit cond: Cond[T]): cond.V = cond.value // true is type! ! cond[true] // "foo" // flase is type! " cond[false] // 23 64
  • 65. Path Dependent type - class A { class B var b: Option[B] = None } 65
  • 66. Path Dependent type - class A { class B var b: Option[B] = None } val a1: A = new A val a2: A = new A val b1: a1.B = new a1.B // a1.B . val b2: a2.B = new a2.B // a1.B a2.B . b1 === b2 // 66
  • 67. Path Dependent type - val b1: a1.B = new a1.B // a1.B . val b2: a2.B = new a2.B // a1.B a2.B . a1.b = Some(b1) a2.b = Some(b1) // does not compile Dependent Type Programming 67
  • 68. Map - . val strIntMap: Map[String, Int] = Map("width" -> 120) 68
  • 69. Map - . val strIntMap: Map[String, Int] = Map("width" -> 120) Sting Map Value ? 69
  • 70. Map - . val strIntMap: Map[String, Int] = Map("width" -> 120) Sting Map Value ? Any val strAnyMap: Map[String, Any] = strIntMap + ("sort" -> "time") 70
  • 71. Map - . val strIntMap: Map[String, Int] = Map("width" -> 120) Sting Map Value ? Any val strAnyMap: Map[String, Any] = strIntMap + ("sort" -> "time") // ? val width: Option[Any] = map2.get("width") val sort: Option[Any] = map2.get("sort") 71
  • 72. HMap - Heterogenous Map1 Dependent type ! 1  Dotty : https://www.slideshare.net/Odersky/from-dot-to-dotty 72
  • 73. HMap - Heterogenous Map1 Dependent type ! trait Key { type Value } trait HMap { def get(key: Key): Option[key.Value] // key Value, dependent type! def add(key: Key)(value: key.Value): HMap } 1  Dotty : https://www.slideshare.net/Odersky/from-dot-to-dotty 73
  • 74. val sort = new Key { type Value = String } val width = new Key { type Value = Int } 74
  • 75. val sort = new Key { type Value = String } val width = new Key { type Value = Int } Key Value val hmap: HMap = HMap.empty .add(width)(120) .add(sort)("time") .add(width)(true) // doesn't compile, width Int Value . 75
  • 76. val sort = new Key { type Value = String } val width = new Key { type Value = Int } Key Value val hmap: HMap = HMap.empty .add(width)(120) .add(sort)("time") .add(width)(true) // doesn't compile, width Int Value . Value . val optionInt: Option[Int] = hmap.get(width) val optionString: Option[String] = hmap.get(sort) 76
  • 78. HMap ! 9 trait HMap { self => val underlying: Map[Any, Any] def get(key: Key): Option[key.Value] = underlying.get(key).map(_.asInstanceOf[key.Value]) def add(key: Key)(value: key.Value): HMap = new HMap { val underlying = self.underlying + (key -> value) } } 78
  • 79. Believing that: Life is Study!4 4  https://twitter.com/ktosopl 79
  • 80. NilOnce your code compiles it usually works. 80
  • 85. Scala in Real World. Parallel Programming in Micro Service Architecture.5 5  http://tech.kakao.com/2017/09/02/parallel-programming-and-applicative-in-scala/ 85
  • 86. 86
  • 87. . SELECT * FROM items, catalogs, wishes, categories, details, certificiations WHERE items.id = ? AND items.id = catalogs.itemId AND items.id = wishes.itemId ... 87
  • 88. . val product: Future[ProductDto] = for { item <- itemReposotory.findByid(itemId) // catalog <- catalogRepository.findById(item.catalogId) // brand <- brandRepository.findById(item.brandId) // wish <- itemWishCountRepository.findByItemId(item.id) // category <- categoryRepository.findOneByBrandId(item.brandId) // detail <- itemDetailRepository.findByItemId(item.id) // cert <- itemCertificationRepository.findByItemId(item.id) // } yield ProductFactory.of(item, brand, catalog, wish, category, detail, cert) 88
  • 89. ? 89
  • 90. . 90
  • 95. Applicative - trait Applicative[F[_]] { def pure[A](a: A): F[A] def ap[A, B](fa: F[A])(ff: F[A => B]): F[B] } 95
  • 96. Applicative - ap import scala.concurrent.Future val futureAp = new Applicative[Future] { def pure[A](a: A) = Future.successful(a) def ap[A, B](fa: Future[A])(ff: Future[A => B]): Future[B] = ff.zip(fa).map { case (f, a) => f(a)} } 96
  • 97. Applicative can be parallel itemRepository.findById(itemId).flatMap { item => ( catalogRepository.findById(item.catalogId) |@| brandRepository.findById(item.brandId) |@| itemWishCountRepository.findByItemId(item.id) |@| categoryRepository.findOneByBrandId(item.brandId) |@| itemDetailRepository.findByItemId(item.id) |@| itemCertificationRepository.findByItemId(item.id) ).map { case (catalog, brand, wish, category, detail, cert) => List(brand, catalog, wish, category, detail, cert) } } 97
  • 98. 98
  • 99. 99
  • 100. Backgroud - Phantom type ! Phantom( ) type Compile time Runtime trait Phantom // type MyInt = Int with Phantom // Phantom type mixin 100
  • 101. Int has no meaning A Int can contains anything Int 42 9496 7296 . 101
  • 102. def findItemsBy(brandId: Int, itemId: Int, status: Int, page: Int, size: Int = 20) = items.filter(_.brandId == brandId).drop(page * size).take(size) // ItemService.scala // . findItemsByBrandId(brandId, itemId, status, page, size) 102
  • 103. ? // catalogId , Id def findItemsBy(brandId: Int, itemId: Int,catalogId: Int, status: Int, page: Int, size: Int = 20) = items.filter(_.brandId == brandId).drop(page * size).take(size) // BrandService.scala // API . findItemsByBrandId(brandId, itemId, catalogId, status, page, size) 103
  • 104. ? // catalogId , Id def findItemsBy(brandId: Int, itemId: Int,catalogId: Int, status: Int, page: Int, size: Int = 20) = items.filter(_.brandId == brandId).drop(page * size).take(size) // BrandService.scala // API . findItemsByBrandId(brandId, itemId, catalogId, status, page, size) // ItemService.scala // ? findItemsByBrandId(brandId, itemId, status, page, size) 104
  • 106. User defined type Compiler . case class ItemId(value: Int) extends AnyVal case class CatalogId(value: Int) extends AnyVal case class BrandId(value: Int) extends AnyVal case class Status(value: Int) extends AnyVal case class Page(value: Int) extends AnyVal case class Size(value: Int) extends AnyVal 106
  • 107. API def findItemsByBrandId( brandId: BrandId, itemId: ItemId, catalogId: CatalogId, status: Status, page: Page, size: Size = Size(20) ): List[Item] = items.filter(_.brandId == brandId.value) .drop(page.value * size.value) .take(size.value) findItemsByBrandId(brandId, itemId, status, page, size) // doesn't compile, 107
  • 108. ? . ! // before def findItemsBy( brandId: Int, itemId: Int,catalogId: Int, status: Int, page: Int, size: Int = 20): List[Item] = items .filter(_.brandId == brandId) .drop(page * size) .take(size) // after def findItemsByBrandId( brandId: BrandId, itemId: ItemId, catalogId: CatalogId, status: Status, page: Page, size: Size = Size(20)): List[Item] = items.filter(_.brandId == brandId.value) .drop(page.value * size.value) // .take(size.value) // ? ! ? " 108
  • 109. Page type Int Int . case class Page(value: Int) extends AnyVal Page Int ? Page extends Int Page Int . val page: Int = Page(1) // . 109
  • 110. shapeless . import shapeless._ val shapely = "Dependent type programming" :: "Generic type programming" :: HNil https://github.com/milessabin/shapeless . 110
  • 111. Tagged type ! Phantom( ) type Compile time ( ) TypeTag @@ Phantom type import shapeless.tag.@@ type Page = Int @@ PageTag // Page Int PageTag val page: Page = tag[PageTag][Int](1) // , 111
  • 112. Tagged type ! Phantom( ) type Compile time TypeTag @@ Phantom type import shapeless.tag.@@ type Page = Int @@ PageTag // Page Int PageTag val page: Page = tag[PageTag][Int](1) // , // PageTag Int page.getClass // => class java.lang.Integer // Int . val int : Int = page 112
  • 113. Phantom type — . — (final) . — API . — . 113
  • 114. import shapeless.tag.@@ trait BrandIdTag; trait ItemIdTag trait BrandTag; trait ItemTag trait PageTag; trait SizeTag object Pagable { type Page = Int @@ PageTag // Page Int type Size = Int @@ SizeTag // Size Int } def findItemsByBrandId(brandId: Int, page: Page, size: Size): List[Item] = items.filter(_.brandId == brandId) .drop(page * size) // Page => Int ! .take(size) // val page: Page = tag[PageTag][Int](1) val size: Size = tag[SizeTag][Int](20) findItemsByBrandId(1, page, size) // works // page size . findItemsByBrandId(1, size, page) // doesn't compile 114